[SDOI2011]染色
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
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
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
Sample Output
3
1
2
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题解:
树剖套路题。
线段树维护三个参数l,r,s,分别表示左边的颜色,右边的颜色以及这段区间中颜色的总数。
合并的时候就看一下左子树的l和右子树的r是否想等,相等就-1。
纯粹当板子题打的,代码应该还算比较好看的
1 //Never forget why you start 2 #include<iostream> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<algorithm> 8 #define ll(x) (x<<1) 9 #define rr(x) (x<<1|1) 10 using namespace std; 11 int n,m; 12 int head[100005],size,a[100005]; 13 struct node{ 14 int next,to; 15 }edge[200005]; 16 void putin(int from,int to){ 17 size++; 18 edge[size].next=head[from]; 19 edge[size].to=to; 20 head[from]=size; 21 } 22 int end[100005],fa[100005],depth[100005],top[100005],cnt[100005],son[100005],pos[100005],ppos[100005],dfscnt; 23 void dfs1(int r,int father){ 24 int i; 25 fa[r]=father; 26 for(i=head[r];i!=-1;i=edge[i].next){ 27 int y=edge[i].to; 28 if(y!=father){ 29 depth[y]=depth[r]+1; 30 dfs1(y,r); 31 cnt[r]+=cnt[y]; 32 if(son[r]==-1||cnt[y]>cnt[son[r]])son[r]=y; 33 } 34 } 35 cnt[r]++; 36 } 37 void dfs2(int r,int tmp){ 38 int i; 39 top[r]=tmp; 40 pos[r]=++dfscnt; 41 ppos[dfscnt]=r; 42 if(son[r]!=-1)dfs2(son[r],tmp); 43 for(i=head[r];i!=-1;i=edge[i].next){ 44 int y=edge[i].to; 45 if(y!=fa[r]&&y!=son[r]) 46 dfs2(y,y); 47 } 48 end[r]=dfscnt; 49 } 50 struct segment{ 51 int l,r,sum,lazy; 52 friend segment operator + (const segment a,const segment b){ 53 segment ans; 54 if(a.sum==0)return b; 55 if(b.sum==0)return a; 56 ans.l=a.l;ans.r=b.r; 57 ans.sum=a.sum+b.sum-(a.r==b.l); 58 return ans; 59 } 60 }sgm[500005],zero; 61 void push_up(int root){ 62 sgm[root].l=sgm[ll(root)].l; 63 sgm[root].r=sgm[rr(root)].r; 64 sgm[root].sum=sgm[ll(root)].sum+sgm[rr(root)].sum-(sgm[ll(root)].r==sgm[rr(root)].l); 65 return; 66 } 67 void build(int root,int left,int right){ 68 if(left==right){ 69 sgm[root].sum=1; 70 sgm[root].l=a[ppos[left]]; 71 sgm[root].r=a[ppos[left]]; 72 return; 73 } 74 if(left>right)return; 75 int mid=(left+right)>>1; 76 build(ll(root),left,mid); 77 build(rr(root),mid+1,right); 78 push_up(root); 79 } 80 void push_down(int root,int left,int right){ 81 if(!sgm[root].lazy)return; 82 sgm[ll(root)].lazy=sgm[rr(root)].lazy=sgm[root].lazy; 83 sgm[ll(root)].sum=sgm[rr(root)].sum=1; 84 sgm[ll(root)].l=sgm[ll(root)].r=sgm[root].lazy; 85 sgm[rr(root)].l=sgm[rr(root)].r=sgm[root].lazy; 86 sgm[root].lazy=0; 87 return; 88 } 89 void insert(int root,int left,int right,int l,int r,int v){ 90 if(l<=left&&right<=r){ 91 sgm[root].lazy=v; 92 sgm[root].l=sgm[root].r=v; 93 sgm[root].sum=1; 94 return; 95 } 96 if(l>right||r<left)return; 97 push_down(root,left,right); 98 int mid=(left+right)>>1; 99 if(l<=mid)insert(ll(root),left,mid,l,r,v); 100 if(mid<r)insert(rr(root),mid+1,right,l,r,v); 101 push_up(root); 102 } 103 segment query(int root,int left,int right,int l,int r){ 104 if(l<=left&&right<=r) 105 return sgm[root]; 106 if(l>right||r<left)return zero; 107 push_down(root,left,right); 108 int mid=(left+right)>>1; 109 segment ansl=zero,ansr=zero; 110 if(l<=mid)ansl=query(ll(root),left,mid,l,r); 111 if(mid<r)ansr=query(rr(root),mid+1,right,l,r); 112 return ansl+ansr; 113 } 114 int query_color(int root,int left,int right,int x){ 115 if(left==right) 116 return sgm[root].l; 117 push_down(root,left,right); 118 int mid=(left+right)>>1; 119 if(x<=mid)return query_color(ll(root),left,mid,x); 120 else return query_color(rr(root),mid+1,right,x); 121 } 122 void chain_add(int x,int y,int v){ 123 int f1=top[x],f2=top[y]; 124 while(f1!=f2){ 125 if(depth[f1]<depth[f2])swap(x,y),swap(f1,f2); 126 insert(1,1,n,pos[f1],pos[x],v); 127 x=fa[f1];f1=top[x]; 128 } 129 if(depth[x]>depth[y])swap(x,y); 130 insert(1,1,n,pos[x],pos[y],v); 131 } 132 int chain_query(int x,int y){ 133 int f1=top[x],f2=top[y],ans=0; 134 while(f1!=f2){ 135 if(depth[f1]<depth[f2])swap(x,y),swap(f1,f2); 136 ans+=query(1,1,n,pos[f1],pos[x]).sum; 137 int a=query_color(1,1,n,pos[f1]); 138 int b=query_color(1,1,n,pos[fa[f1]]); 139 if(a==b)ans--; 140 x=fa[f1];f1=top[x]; 141 } 142 if(depth[x]>depth[y])swap(x,y); 143 ans+=query(1,1,n,pos[x],pos[y]).sum; 144 return ans; 145 } 146 void clean(){ 147 memset(head,-1,sizeof(head)); 148 memset(son,-1,sizeof(son)); 149 size=0; 150 } 151 int main(){ 152 int i,j; 153 clean(); 154 scanf("%d%d",&n,&m); 155 for(i=1;i<=n;i++) 156 scanf("%d",&a[i]); 157 for(i=1;i<n;i++){ 158 int u,v; 159 scanf("%d%d",&u,&v); 160 putin(u,v); 161 putin(v,u); 162 } 163 depth[1]=1; 164 dfs1(1,0); 165 dfs2(1,0); 166 build(1,1,n); 167 for(i=1;i<=m;i++){ 168 char s[2];int a,b,c; 169 scanf("%s%d%d",s,&a,&b); 170 if(s[0]=='C'){ 171 scanf("%d",&c); 172 chain_add(a,b,c); 173 } 174 else{ 175 printf("%d\n",chain_query(a,b)); 176 } 177 } 178 return 0; 179 }