AC日记——[SDOI2011]染色 洛谷 P2486
Posted Only U - IU
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC日记——[SDOI2011]染色 洛谷 P2486相关的知识,希望对你有一定的参考价值。
题目描述
输入输出格式
输入格式:
输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
输入样例#1:
6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q 3 5 C 5 1 2 Q 3 5
输出样例#1:
3 1 2
说明
思路:
树剖+线段树维护区间颜色数量
来,上代码:
#include <cstdio> #include <iostream> #include <algorithm> #define maxn 200001 using namespace std; struct TreeNodeType { int l,r,dis,lc,rc,flag,mid; }; struct TreeNodeType tree[maxn<<2]; struct EdgeType { int to,next; }; struct EdgeType edge[maxn<<1]; int n,m,if_z,dis[maxn],flag[maxn],dis_[maxn]; int size[maxn],head[maxn],deep[maxn],f[maxn]; int cnt,tot,num,belong[maxn]; char Cget; inline void read_int(int &now) { now=0,if_z=1,Cget=getchar(); while(Cget>‘9‘||Cget<‘0‘) { if(Cget==‘-‘) if_z=-1; Cget=getchar(); } while(Cget>=‘0‘&&Cget<=‘9‘) { now=now*10+Cget-‘0‘; Cget=getchar(); } now*=if_z; } inline void edge_add(int from,int to) { edge[++num].to=from,edge[num].next=head[to],head[to]=num; edge[++num].to=to,edge[num].next=head[from],head[from]=num; } void search(int now,int fa) { int pos=cnt++; deep[now]=deep[fa]+1,f[now]=fa; for(int i=head[now];i;i=edge[i].next) { if(edge[i].to==fa) continue; search(edge[i].to,now); } size[now]=cnt-pos; } void search_(int now,int chain) { belong[now]=chain,flag[now]=++cnt; dis_[flag[now]]=dis[now]; int pos=0; for(int i=head[now];i;i=edge[i].next) { if(edge[i].to==f[now]) continue; if(size[edge[i].to]>size[pos]) pos=edge[i].to; } if(pos!=0) search_(pos,chain); else return ; for(int i=head[now];i;i=edge[i].next) { if(edge[i].to==f[now]||edge[i].to==pos) continue; search_(edge[i].to,edge[i].to); } } inline void tree_up(int now) { if(tree[now<<1].rc==tree[now<<1|1].lc) { tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis-1; } else { tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis; } tree[now].lc=tree[now<<1].lc,tree[now].rc=tree[now<<1|1].rc; } inline void tree_down(int now) { if(tree[now].l==tree[now].r) return ; tree[now<<1].dis=1,tree[now<<1|1].dis=1; tree[now<<1].lc=tree[now<<1].rc=tree[now].flag; tree[now<<1|1].lc=tree[now<<1|1].rc=tree[now].flag; tree[now<<1].flag=tree[now<<1|1].flag=tree[now].flag; tree[now].flag=0; } void tree_build(int now,int l,int r) { tree[now].l=l,tree[now].r=r; if(l==r) { tree[now].lc=dis_[++cnt]; tree[now].rc=tree[now].lc; tree[now].dis=1; return ; } tree[now].mid=(l+r)>>1; tree_build(now<<1,l,tree[now].mid); tree_build(now<<1|1,tree[now].mid+1,r); tree_up(now); } void tree_change(int now,int l,int r,int x) { if(tree[now].l==l&&tree[now].r==r) { tree[now].dis=1,tree[now].flag=x; tree[now].lc=tree[now].rc=x; return ; } if(tree[now].flag) tree_down(now); if(l>tree[now].mid) tree_change(now<<1|1,l,r,x); else if(r<=tree[now].mid) tree_change(now<<1,l,r,x); else { tree_change(now<<1,l,tree[now].mid,x); tree_change(now<<1|1,tree[now].mid+1,r,x); } tree_up(now); } int tree_query(int now,int l,int r) { if(tree[now].l==l&&tree[now].r==r) { return tree[now].dis; } if(tree[now].flag) tree_down(now); tree_up(now); if(l>tree[now].mid) return tree_query(now<<1|1,l,r); else if(r<=tree[now].mid) return tree_query(now<<1,l,r); else { int ld=tree_query(now<<1,l,tree[now].mid); int rd=tree_query(now<<1|1,tree[now].mid+1,r); if(tree[now<<1].rc==tree[now<<1|1].lc) return ld+rd-1; else return ld+rd; } } int tree_query_color(int now,int to) { if(tree[now].l==tree[now].r&&tree[now].l==to) { return tree[now].lc; } if(tree[now].flag) tree_down(now); tree_up(now); if(to>tree[now].mid) return tree_query_color(now<<1|1,to); else return tree_query_color(now<<1,to); } inline void solve_change(int x,int y,int z) { while(belong[x]!=belong[y]) { if(deep[belong[x]]<deep[belong[y]]) swap(x,y); tree_change(1,flag[belong[x]],flag[x],z); x=f[belong[x]]; } tree_change(1,min(flag[x],flag[y]),max(flag[x],flag[y]),z); } inline int solve_query(int x,int y) { int ans=0; while(belong[x]!=belong[y]) { if(deep[belong[x]]<deep[belong[y]]) swap(x,y); ans+=tree_query(1,flag[belong[x]],flag[x]); if(tree_query_color(1,flag[belong[x]])==tree_query_color(1,flag[f[belong[x]]])) ans--; x=f[belong[x]]; } ans+=tree_query(1,min(flag[x],flag[y]),max(flag[x],flag[y])); return ans; } int main() { read_int(n),read_int(m); for(int i=1;i<=n;i++) read_int(dis[i]); int from,to,pos; for(int i=1;i<n;i++) { read_int(from),read_int(to); edge_add(from,to); } search(1,0),cnt=0,search_(1,1),cnt=0,tree_build(1,1,n); char type; for(int i=1;i<=m;i++) { cin>>type; if(type==‘C‘) { read_int(from),read_int(to),read_int(pos); solve_change(from,to,pos); } else { read_int(from),read_int(to); printf("%d\n",solve_query(from,to)); } } return 0; }
以上是关于AC日记——[SDOI2011]染色 洛谷 P2486的主要内容,如果未能解决你的问题,请参考以下文章