可爱的树链剖分(染色)

这道题 就是 一道 普通的! 树链剖分+线段树覆盖

注意一下两个线段树合并的时候 如果 \(lval(node<<1|1)==rval(node<<1)\) 相当于这两个线段树的相邻的数字数相同的 那么合并时的\(tot\) \(sum\) 应该 --

所以说这道题有什么细节吗 我感觉是没有的 然而我调了一下午+晚上两个小时 (再次感谢人帅心善的kma小哥哥) (话说为什么他有这么多女朋友,而我还是单身呢) 不 我有萌德

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int maxn=1e6+10;
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*10+ch-'0';ch=getchar();};
	return x*f;
}
int n,m,color[maxn],fir[maxn<<1],nxt[maxn<<1],to[maxn<<1],tot,top[maxn];
int size[maxn],son[maxn],fa[maxn],rk[maxn],id[maxn],dep[maxn],times;
char op[3];
struct nodee{
	int l,r,lval,rval,sum,tag;
	#define lval(x) tree[x].lval
	#define rval(x) tree[x].rval
	#define l(x) tree[x].l
	#define r(x) tree[x].r
	#define sum(x) tree[x].sum
	#define tag(x) tree[x].tag
}tree[maxn<<4];
void add(int x,int y){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;}
void dfs1(int x){
	dep[x]=dep[fa[x]]+1;size[x]=1;
	for(int i=fir[x];i;i=nxt[i]){
		int y=to[i];if(y==fa[x]) continue;
		fa[y]=x;dfs1(y);size[x]+=size[y];
		if(size[son[x]]<size[y]) son[x]=y;
	}
}
void dfs2(int x,int tp){
	top[x]=tp;id[x]=++times;rk[times]=x;
	if(son[x]) dfs2(son[x],tp);
	for(int i=fir[x];i;i=nxt[i]){
		int y=to[i];if(id[y]) continue;
		dfs2(y,y);
	}
}
void push_up(int node){
	lval(node)=lval(node<<1);rval(node)=rval(node<<1|1);
	sum(node)=sum(node<<1)+sum(node<<1|1);
	if(rval(node<<1)==lval(node<<1|1))	--sum(node);
}
void build(int node,int l,int r){
	l(node)=l;r(node)=r;
	if(l==r){
		lval(node)=rval(node)=color[rk[l]];
		sum(node)=1;return ;
	}
	int mid=l+r>>1;
	build(node<<1,l,mid);build(node<<1|1,mid+1,r);
	push_up(node);
}
void push_down(int node){
	if(tag(node)){
		tag(node<<1)=tag(node<<1|1)=tag(node);
		lval(node<<1)=rval(node<<1)=lval(node<<1|1)=rval(node<<1|1)=tag(node);
		sum(node<<1)=sum(node<<1|1)=1;
		tag(node)=0;
	}
}
void modify(int node,int ql,int qr,int z){
	if(ql<=l(node) && r(node)<=qr){
		sum(node)=1;tag(node)=z;
		lval(node)=z;rval(node)=z;
		return ;
	}
	push_down(node);
	int mid=l(node)+r(node)>>1;
	if(ql<=mid)	modify(node<<1,ql,qr,z);
	if(mid<qr) modify(node<<1|1,ql,qr,z);
	push_up(node);
}
void chain_modify(int x,int y,int z){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]){
			x^=y^=x^=y;
		}
		modify(1,id[top[x]],id[x],z);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])	x^=y^=x^=y;
	modify(1,id[y],id[x],z);
	return ;
}
int Rval = 0,Lval = 0,last1 = 0,last2 = 0;
int query(int node,int ql,int qr){
	if(ql==l(node))	Lval=lval(node);
	if(qr==r(node))	Rval=rval(node);
	if(ql<=l(node) && r(node)<=qr){
		return sum(node);
	}
	push_down(node);
	int ans=0,mid=l(node)+r(node)>>1;
	if(ql>mid) ans+=query(node<<1|1,ql,qr);
	else if (qr <= mid) ans += query(node<<1,ql,qr);
	else {
			if(rval(node<<1)==lval(node<<1|1))	ans+=query(node<<1,ql,qr)+query(node<<1|1,ql,qr)-1;
		else ans+=query(node<<1,ql,qr)+query(node<<1|1,ql,qr);
	}
	return ans;
}
int chain_query(int x,int y){
	last1 = 0, last2 = 0, Lval = 0, Rval = 0;
	int tx=top[x],ty=top[y];
	int ans=0;
	while(tx!=ty){
		if(dep[tx]<dep[ty]){
			x^=y^=x^=y;
			tx^=ty^=tx^=ty;
			last1^=last2^=last1^=last2;
		}
		ans+=query(1,id[tx],id[x]);
		if(last1==Rval)	--ans;
		last1=Lval;
		x=fa[tx];tx=top[x];
	}
	if(dep[x]<dep[y]){
		x^=y^=x^=y;
		last1^=last2^=last1^=last2;
	}
	ans+=query(1,id[y],id[x]);
	if(Rval==last1) ans--;
	if(Lval==last2) ans--;
	return ans;
}
signed main(){
	n=read();m=read();
	for(int i=1;i<=n;i++)
		color[i]=read();
	for(int i=1,x,y;i<=n-1;i++){
		x=read();y=read();
		add(x,y);add(y,x);
	}
	dfs1(1);dfs2(1,1);
	build(1,1,n);
	for(int i=1,x,y,z;i<=m;i++){
		scanf("%s",op + 1);x=read();y=read();
		if(op[1]=='C') {
			z=read();chain_modify(x,y,z);
		}
		if(op[1]=='Q') printf("%lld\n",chain_query(x,y));
	}
	return 0;
}

但是注意一下 在chain_query 和 chain_modify 的时候 最后的判断语句一定不能改方向(为什么呢我不知道) 我好难受啊

posted on 2019-10-28 21:16  萌德真帅  阅读(165)  评论(0编辑  收藏  举报