可爱的树链剖分(染色)
这道题 就是 一道 普通的! 树链剖分+线段树覆盖
注意一下两个线段树合并的时候 如果 (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
",chain_query(x,y));
}
return 0;
}
但是注意一下 在chain_query 和 chain_modify 的时候 最后的判断语句一定不能改方向(为什么呢我不知道) 我好难受啊