【Luogu】P2486染色(树链剖分)
线段树维护左端颜色,右端颜色,颜色段数量。
合并的时候看左子树的右端颜色是不是等于右子树的左端颜色,如果等于那么颜色段数量要-1S
然后在树剖跳链的时候搞同样的操作qwq
然后就没有然后了
#include<cstdio> #include<algorithm> #include<cstring> #include<cctype> #include<cstdlib> #define maxn 500000 #define left (rt<<1) #define right (rt<<1|1) #define mid ((l+r)>>1) #define lson l,mid,left #define rson mid+1,r,right using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int n,m; int tag[maxn*2]; int deep[maxn]; int dfn[maxn],ID; int back[maxn]; int q[maxn]; int son[maxn]; int top[maxn]; int father[maxn]; int size[maxn]; struct Edge{ int next,to; }edge[maxn*2]; int head[maxn],num; inline void add(int from,int to){ edge[++num]=(Edge){head[from],to}; head[from]=num; } struct Node{ int lcol,rcol,ncol; Node operator +(const Node a){ Node ans=(Node){lcol,a.rcol,ncol+a.ncol}; if(rcol==a.lcol) ans.ncol--; return ans; } }tree[maxn*2]; inline void pushup(int rt){ tree[rt]=tree[left]+tree[right]; } inline void pushdown(int rt){ if(tag[rt]==0) return; tag[left]=tag[right]=tag[rt]; tree[left].lcol=tree[right].lcol=tree[left].rcol=tree[right].rcol=tag[rt]; tree[left].ncol=tree[right].ncol=1; tag[rt]=0; } void build(int l,int r,int rt){ if(l==r){ int last=back[l]; tree[rt]=(Node){q[last],q[last],1}; return; } build(lson); build(rson); pushup(rt); } void update(int from,int to,int num,int l,int r,int rt){ if(from<=l&&to>=r){ tree[rt]=(Node){num,num,1}; tag[rt]=num; return; } pushdown(rt); if(from<=mid) update(from,to,num,lson); if(to>mid) update(from,to,num,rson); pushup(rt); return; } int query(int from,int to,int l,int r,int rt){ if(from<=l&&to>=r) return tree[rt].ncol; pushdown(rt); int ans=0; if(from<=mid) ans+=query(from,to,lson); if(to>mid) ans+=query(from,to,rson); if(from<=mid&&to>mid) if(tree[left].rcol==tree[right].lcol) ans--; return ans; } int qucol(int o,int l,int r,int rt){ if(l==r) return tree[rt].lcol; pushdown(rt); if(o<=mid) return qucol(o,lson); else return qucol(o,rson); } void findfs(int x,int fa){ deep[x]=deep[fa]+1; size[x]=1; father[x]=fa; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==fa) continue; findfs(to,x); size[x]+=size[to]; if(son[x]==0||size[son[x]]<size[to]) son[x]=to; } } void unidfs(int x,int Top){ top[x]=Top; dfn[x]=++ID; back[ID]=x; if(son[x]==0) return; unidfs(son[x],Top); for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==father[x]||to==son[x]) continue; unidfs(to,to); } } void uplink(int from,int to,int num){ while(top[from]!=top[to]){ if(deep[top[from]]<deep[top[to]]) swap(from,to); update(dfn[top[from]],dfn[from],num,1,n,1); from=father[top[from]]; } if(deep[from]>deep[to]) swap(from,to); update(dfn[from],dfn[to],num,1,n,1); } int qulink(int from,int to){ int ans=0; while(top[from]!=top[to]){ if(deep[top[from]]<deep[top[to]]) swap(from,to); ans+=query(dfn[top[from]],dfn[from],1,n,1); from=top[from]; if(qucol(dfn[from],1,n,1)==qucol(dfn[father[from]],1,n,1)) ans--; from=father[from]; } if(deep[from]>deep[to]) swap(from,to); ans+=query(dfn[from],dfn[to],1,n,1); return ans; } int main(){ n=read(),m=read(); for(int i=1;i<=n;++i) q[i]=read(); for(int i=1;i<n;++i){ int from=read(),to=read(); add(from,to); add(to,from); } findfs(1,1); unidfs(1,1); build(1,n,1); for(int i=1;i<=m;++i){ char ch[10]; int a,b; scanf("%s%d%d",ch,&a,&b); if(ch[0]=='Q') printf("%d\n",qulink(a,b)); else if(ch[0]=='C'){ int c=read(); uplink(a,b,c); } } return 0; }