广义线段树上树剖再拿线段树维护:0914T4

news2024/11/27 6:20:09

cp

一种常见套路(也是广义线段树问题的核心解决方法,UNR1好像也有一题):

如果在线段树上进行一段区间修改,那么必然是一段右节点+一段左节点

这个过程其实就是zkw的本质

下面都要用zkw来理解

考虑原题,有一棵不规则的线段树

类似zkw,在这类题目中,我们要先把开区间变成闭区间

然后每个点记录其兄弟节点的信息

考虑现在区间为 ( x , y ) (x,y) (x,y),我们可以先求出其 z = l c a ( x , y ) z=lca(x,y) z=lca(x,y)

x x x 要跳到 l s [ z ] ls[z] ls[z] y y y 要跳到 r s [ z ] rs[z] rs[z]

x x x 在跳的过程中,如果它是左节点那么就修改/统计它的右节点

我们可以回顾zkw的过程帮助理解:

在这里插入图片描述
然后现在考虑优化跳的这个过程。

我们发现这就是个树剖。

然后就完成啦

时间复杂度 O ( n log ⁡ 2 n ) O(n\log^2n) O(nlog2n)

线段树套线段树

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||
ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back

#define N 400010
int n, m, i, j, k, T;
int f[N][22], q, x, y, ans, dep[N], lxy, op, d, mp[N]; 

struct Segment_tree {
	int tot, ls[N<<1], rs[N<<1], rt; 
	int s[N<<1], tag[N<<1], len[N<<1]; 
	void build(int &k, int l, int r) {
		if(!k) k=++tot; 
		if(l==r) return ; 
		int mid=(l+r)>>1; 
		build(ls[k], l, mid); 
		build(rs[k], mid+1, r); 
	}
	void make(int k, int l, int r, int x, int y) {
		if(l==r) return len[k]=y, void(); 
		int mid=(l+r)>>1; 
		if(x<=mid) make(ls[k], l, mid, x, y); 
		else make(rs[k], mid+1, r, x, y); 
		len[k]=len[ls[k]]+len[rs[k]]; 
	}
	void add(int k, int l, int r, int x, int y, int z) {
		if(l>=x && r<=y) {
			tag[k]+=z; s[k]+=len[k]*z; 
			return ; 
		}
		tag[ls[k]]+=tag[k]; s[ls[k]]+=len[ls[k]]*tag[k]; 
		tag[rs[k]]+=tag[k]; s[rs[k]]+=len[rs[k]]*tag[k]; 
		tag[k]=0; 
		int mid=(l+r)>>1;  
		if(x<=mid) add(ls[k], l, mid, x, y, z); 
		if(y>=mid+1) add(rs[k], mid+1, r, x, y, z); 
		s[k]=s[ls[k]]+s[rs[k]]; 
	}
	int que(int k, int l, int r, int x, int y) {
		if(l>=x && r<=y) return s[k]; 
		int mid=(l+r)>>1, sum=0; 
		tag[ls[k]]+=tag[k]; s[ls[k]]+=len[ls[k]]*tag[k]; 
		tag[rs[k]]+=tag[k]; s[rs[k]]+=len[rs[k]]*tag[k]; 
		tag[k]=0; 
		if(x<=mid) sum+=que(ls[k], l, mid, x, y); 
		if(y>=mid+1) sum+=que(rs[k], mid+1, r, x, y); 
		return sum; 
	}
}S1, S2;

struct Tree_chain_pou_score {
	int ls[N], rs[N], tot; 
	int w[N], st[N], ed[N], len[N]; 
	int up[N], dfn[N], p[N]; 
	int son[N], ltson[N]; 
	void dfs1(int x) {
		if(x<=n) {
			st[x]=ed[x]=x; w[x]=1; 
			return ; 
		}
		f[ls[x]][0]=f[rs[x]][0]=x; 
		dep[ls[x]]=dep[rs[x]]=dep[x]+1; 
		dfs1(ls[x]); dfs1(rs[x]); 
		st[x]=st[ls[x]]; ed[x]=ed[rs[x]]; 
		w[x]=w[ls[x]]+w[rs[x]]+1; 
	}
	void dfs2(int x, int Up) {
		up[x]=Up; dfn[x]=++tot; p[x]=tot;  
		len[x]=ed[x]-st[x]+1; 
		if(x<=n) return ; 
		if(w[ls[x]]>w[rs[x]]) son[x]=ls[x], ltson[x]=rs[x]; 
		else son[x]=rs[x], ltson[x]=ls[x]; 
		dfs2(son[x], Up); 
		dfs2(ltson[x], ltson[x]); 
		S1.make(1, 1, m, dfn[ls[x]], len[rs[x]]); 
		S2.make(1, 1, m, dfn[rs[x]], len[ls[x]]); 
	}
	void add(Segment_tree &Seg, int x, int y, int z) {
		while(up[x]!=up[y]) {
			Seg.add(1, 1, m, dfn[up[x]], dfn[x], z); 
			x=f[up[x]][0]; 
		}
		if(x==y) return ; 
		Seg.add(1, 1, m, dfn[y]+1, dfn[x], z); 
	}
	int que(Segment_tree &Seg, int x, int y) {
		int ans=0; 
		while(up[x]!=up[y]) {
			ans+=Seg.que(1, 1, m, dfn[up[x]], dfn[x]); 
			x=f[up[x]][0]; 
		}
		if(x==y) return ans; 
		ans+=Seg.que(1, 1, m, dfn[y]+1, dfn[x]); 
		return ans; 
	}
}Tree;

int lca(int x, int y) {
	if(x==y) return x; 
	if(dep[x]<dep[y]) swap(x, y); 
	for(int k=20; k>=0; --k)
		if(dep[f[x][k]]>=dep[y]) x=f[x][k]; 
	if(x==y) return x; 
	for(int k=20; k>=0; --k)
		if(f[x][k]!=f[y][k]) x=f[x][k], y=f[y][k]; 
	return f[x][0]; 
}

signed main()
{
	freopen("pigeons.in", "r", stdin);
	freopen("pigeons.out", "w", stdout);
	n=read(); q=read(); 
	for(i=n+1; i<2*n; ++i) {
		Tree.ls[i+2]=read(); Tree.rs[i+2]=read(); 
		if(Tree.ls[i+2]<=n) Tree.ls[i+2]++; 
		else Tree.ls[i+2]+=2; 
		if(Tree.rs[i+2]<=n) Tree.rs[i+2]++; 
		else Tree.rs[i+2]+=2; 
		mp[Tree.ls[i+2]]=mp[Tree.rs[i+2]]=1; 
	}
	for(i=n+3; mp[i]; ++i); 
	Tree.ls[2*n+2]=1; Tree.rs[2*n+2]=i; 
	Tree.ls[2*n+3]=2*n+2; Tree.rs[2*n+3]=n+2; 
	m=2*n+3; n=n+2; 
	dep[m]=1; Tree.dfs1(m); 
	S1.build(S1.rt, 1, m); S2.build(S2.rt, 1, m); 
	Tree.dfs2(m, m); 
	for(k=1; k<=20; ++k)
		for(i=1; i<=m; ++i) {
			f[i][k]=f[f[i][k-1]][k-1]; 
		}
	while(q--) {
		op=read(); 
		if(op==1) {
			x=read()+1; y=read()+1; d=read(); 
			lxy=lca(x-1, y+1); 
			Tree.add(S1, x-1, Tree.ls[lxy], d); 
			Tree.add(S2, y+1, Tree.rs[lxy], d); 
		}
		else {
			x=read()+1; y=read()+1; 
			lxy=lca(x-1, y+1); ans=0; 
			ans+=Tree.que(S1, x-1, Tree.ls[lxy]); 
			ans+=Tree.que(S2, y+1, Tree.rs[lxy]); 
			printf("%lld\n", ans); 
		}
	}
	return 0;
}



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1028913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VR全景拍摄:打破传统拍摄角度限制,营造全新体验

VR全景拍摄不仅仅是拍摄环境&#xff0c;更多的是展示意境&#xff0c;我们的传统文化就是讲究意境&#xff0c;仅仅是看一张清晰无比的图片&#xff0c;自然显得没有趣味&#xff0c;但是这种真实的视觉体验&#xff0c;明明不在现场却能直观体验现场场景&#xff0c;这种意境…

SHIBUYA109 首次推出的人物化身系列!

准备好迎接由 SHIBUYA109 监督设计的原创人物化身系列&#xff0c;名为“SHIBUYA109 时尚系列 2023”&#xff0c;以各种引领潮流的时尚为特色。这个限量系列融合了日本的潮流和文化&#xff0c;全球仅有 2060 个独一无二的人物化身&#xff08;其中 2000 个限量发售&#xff0…

【JVM】类加载的过程

文章目录 类的生命周期加载验证准备解析初始化简要概括 类的生命周期 一个类型从被加载到虚拟机内存中开始&#xff0c;到卸载出内存为止&#xff0c;它的整个生命周期将会经历加载 &#xff08;Loading&#xff09;、验证&#xff08;Verification&#xff09;、准备&#xf…

基于SSM+Vue的网络教学平台的设计与实现的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

抖音开网店无货源怎么找

随着社交媒体的快速发展&#xff0c;抖音已经成为了一种极具潜力的电商平台。许多人想要利用这个平台开设网店&#xff0c;但是其中很多人面临的问题是如何找到货源。无货源的抖音网店经营固然具有一定的难度&#xff0c;但并非不可行。以下是一些帮助你在抖音开网店无货源的方…

idea中maven项目打包成jar,报错没有主清单属性解决方法

使用idea自带的打包可能会出现一下问题 在pom.xml中引入下面的依赖&#xff0c;即可解决 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions&…

Linux 多线程 | 线程安全、死锁、线程同步

在前面的文章中我们讲述了锁的理解、原理、用户级线程库的内容&#xff0c;以及对Linux中的锁和线程进行了封装&#xff0c;本文中将继续对多线程的内容进行讲解。 可重入与线程安全 概念 线程安全&#xff1a;多个线程并发同一段代码时&#xff0c;不会出现不同的结果。常见…

ImGui显示中文

ImGui显示中文 前言 首先要加载中文字体&#xff0c;相信大家在网上能搜到或者某些教程都是这么说明的&#xff0c;或者说在字符串前面加上u8前缀的&#xff0c; 例如&#xff1a;ImGui::Text(u8"中文中文 chinese.");&#xff0c;但是大概率中文还是??&#xff…

Java虚拟机:内存区域分配和对象的创建

Java虚拟机&#xff1a;内存区域分配和对象的创建 虚拟机内存区域分配 首先上一张图&#xff1a; 这里主要是看右边的图&#xff0c;这张图描述了JVM中的内存分配区域&#xff0c;其中蓝色的部分是每个线程独有的&#xff0c;而绿色部分是线程共有的。我们以这张图为准&…

iptables 四表五链图

iptables 通过配置四表五链&#xff0c;来控制内核多数据包的过滤、记录、转发、修改操作 全局结构图 常用的 filter 和 nat 表联合图 各个表拥有的链图

传导和辐射EMI有什么区别?

当我们设计原型或使用开发板时&#xff0c;通常可以忽略电磁干扰。但EMI在现实生活中的电子设备和系统中是一个重要的主题&#xff0c;工程师有责任确保电路能够在预期的EMI水平下正常运行&#xff0c;并且不会产生过多的EMI。 我倾向于将EMI与无线干扰联系起来&#xff0c;考…

Nginx服务优化措施、网页安全与配置防盗链

目录 一.优化Nginx 二.隐藏/查看版本号 隐藏版本号方法一&#xff1a;修改配置文件&#xff0c;关闭版本号 隐藏版本号方法二&#xff1a;修改源码文件中的版本号&#xff0c;重新编译安装 三.修改用户与组 四.设置缓存时间 五.日志切割脚本 六.设置连接超时控制连接访…

nvme_queue_rq函数分析一

nvme I/O请求时&#xff0c;数据交互分析 主要函数为nvme_queue_rq&#xff1a; static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) {struct nvme_ns *ns hctx->queue->queuedata;struct nvme_queue *nvmeq hctx-…

elementui表单的验证问题

elementui表单的验证问题 element ui是基于vue的一个ui框架&#xff0c;用起来还是挺不错的&#xff0c;但是有时候还是会遇到一些摸不着头脑的情况。 ​ 我在打开一个新增数据的对话框的时候出现了一个问题&#xff0c;明明是新增&#xff0c;但是一打开就出现了错误提示&…

Linux虚拟化指南:构建虚拟化环境

虚拟化技术在计算领域具有广泛的应用&#xff0c;能够提高硬件资源的利用率、降低维护成本&#xff0c;并实现灵活的资源分配。Linux作为一种开源操作系统&#xff0c;在虚拟化方面也有多种选择和工具可供使用。下面将介绍如何构建Linux虚拟化环境&#xff0c;并提供一些建议和…

skywalking入门

参考&#xff1a; https://www.jianshu.com/p/ffa7ddcda4ab 参考&#xff1a; https://developer.aliyun.com/article/1201085 skywalking&#xff08;APM&#xff09; 调用链路分析以及应用监控分析工具 Skywalking主要由三大部分组成&#xff1a;agent、collector、webapp-…

强怼美国政府,Zlibrary高调复活,官宣2023年最新网址,免费下载海量电子书籍

去年11月&#xff0c;号称是全球最大电子图书馆的Z-Library被美国FBI封禁&#xff0c;连同下线的还有多达249个备用、影子、镜像、关联域名等。 随后&#xff0c;美司法部在阿根廷逮捕了Z-Library网站幕后的两位策划者。他们被控盗取文化作品牟利&#xff0c;经常在新书出版后几…

HTML5中使用video标签

参考链接 <videocontrolscontrolslist"nodownload noplaybackrate"disablePictureInPicture"true"disableRemotePlayback"true"src"https://www.runoob.com/try/demo_source/movie.mp4"></video>隐藏下载&#xff1a;nod…

ElasticSearch从入门到精通(一)

1. 初识 ElasticSearch 传统数据库查询的问题&#xff1a;如果使用模糊查询&#xff0c;左边有通配符&#xff0c;不会走索引&#xff0c;全表扫描&#xff0c;效率比较慢 倒排索引 将文档进行分词&#xff0c;形成词条和 id 的对应关系即为反向索引。 以唐诗为例&#xff0c…

解决域控制器的传感器配置问题

gpu加速计划 下载东西有时会报没有apt-utils&#xff0c;所以最好先给它下了&#xff1a; sudo apt-get install apt-utils验证&#xff1a; python #输入库 import torch #查看版本 print(torch.__version__) #查看gpu是否可用 torch.cuda.is_available() #返回设备gpu个数…