题目描述
输入输出格式
输入格式:
输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
输入样例#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
说明
题解:
树剖,用线段树维护:
数组tot[N]表示此时的颜色段数。
数组zzz[N]表示此时最左边的节点的颜色。
数组yyy[N]表示此时最右边的节点的颜色。
则: 首先我们要明确,线段树的叶子节点一定只有一种颜色,也就是一条颜色段。
tot[父亲]=tot[左儿子]+tot[右儿子];
if (zzz[右儿子]==yyy[左儿子]) {tot[父亲]--;}
即如果右儿子的最左边颜色和左儿子的最右边颜色相同,那么肯定有中间部分属于同一颜色段。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define k (z+y>>1) 5 #define ll (r<<1) 6 #define rr (r<<1|1) 7 using namespace std; 8 const int N=1e5+10;int a[N]; 9 int ys[N],s[N*2][2],o[N],cnt,dfn,n; 10 int zzz[N*4],yyy[N*4],laz[N*4],tot[N*4]; 11 int d[N],siz[N],son[N],top[N],f[N],id[N]; 12 void jia(int a,int b) 13 { 14 s[++cnt][1]=o[a]; 15 s[cnt][0]=b;o[a]=cnt; 16 return; 17 } 18 void shang(int r) 19 { 20 tot[r]=tot[ll]+tot[rr]; 21 zzz[r]=zzz[ll];yyy[r]=yyy[rr]; 22 if (zzz[rr]==yyy[ll]) tot[r]--; 23 return; 24 } 25 void xiangxia(int r,int z,int y) 26 { 27 tot[ll]=tot[rr]=1; 28 zzz[ll]=zzz[rr]=yyy[ll]=yyy[rr]=laz[ll]=laz[rr]=laz[r]; 29 laz[r]=0;return; 30 } 31 void jianshu(int r,int z,int y) 32 { 33 if (z==y) { 34 tot[r]=1;zzz[r]=yyy[r]=ys[a[z]]; 35 return; 36 } 37 jianshu(ll,z,k);jianshu(rr,k+1,y); 38 shang(r);return; 39 } 40 void gai(int r,int z,int y,int zz,int yy,int v) 41 { 42 if (z==zz&&y==yy) { 43 tot[r]=1;laz[r]=zzz[r]=yyy[r]=v; 44 return; 45 } 46 if (laz[r]) xiangxia(r,z,y); 47 if (zz>k) gai(rr,k+1,y,zz,yy,v); 48 else if (yy<=k) gai(ll,z,k,zz,yy,v); 49 else {gai(ll,z,k,zz,k,v);gai(rr,k+1,y,k+1,yy,v);} 50 shang(r);return; 51 } 52 int chaxun(int r,int z,int y,int zz,int yy) 53 { 54 if (z==zz&&y==yy) return tot[r]; 55 if (laz[r]) xiangxia(r,z,y); 56 if (zz>k) chaxun(rr,k+1,y,zz,yy); 57 else if (yy<=k) chaxun(ll,z,k,zz,yy); 58 else { 59 int ans=chaxun(ll,z,k,zz,k)+chaxun(rr,k+1,y,k+1,yy); 60 if (zzz[rr]==yyy[ll]) ans--; 61 return ans; 62 } 63 } 64 void dfs1(int x,int fa,int dep) 65 { 66 f[x]=fa;d[x]=dep;siz[x]=1; 67 for (int i=o[x];i;i=s[i][1]) { 68 if (s[i][0]!=fa) { 69 dfs1(s[i][0],x,dep+1); 70 siz[x]+=siz[s[i][0]]; 71 if (siz[s[i][0]]>siz[son[x]]) son[x]=s[i][0]; 72 } 73 } 74 return; 75 } 76 void dfs2(int x,int tp) 77 { 78 top[x]=tp;id[x]=++dfn;a[dfn]=x; 79 if (son[x]) dfs2(son[x],tp); 80 for (int i=o[x];i;i=s[i][1]) 81 if (s[i][0]!=f[x]&&son[x]!=s[i][0]) 82 dfs2(s[i][0],s[i][0]); 83 return; 84 } 85 void ranse(int x,int y,int v) 86 { 87 while (top[x]!=top[y]) { 88 if (d[top[x]]>d[top[y]]) swap(x,y); 89 gai(1,1,n,id[top[y]],id[y],v); 90 y=f[top[y]]; 91 } 92 if (d[x]>d[y]) swap(x,y); 93 gai(1,1,n,id[x],id[y],v); 94 return; 95 } 96 int newww(int r,int z,int y,int p) 97 { 98 if (z==y) return zzz[r]; 99 if (laz[r]) xiangxia(r,z,y); 100 if (p>k) return newww(rr,k+1,y,p); 101 else return newww(ll,z,k,p); 102 } 103 int xunwen(int x,int y) 104 { 105 int ans=0,nc,fc; 106 while (top[x]!=top[y]) { 107 if (d[top[x]]>d[top[y]]) swap(x,y); 108 ans+=chaxun(1,1,n,id[top[y]],id[y]); 109 nc=newww(1,1,n,id[top[y]]); 110 fc=newww(1,1,n,id[f[top[y]]]); 111 y=f[top[y]];if (nc==fc) ans--; 112 } 113 if (d[x]>d[y]) swap(x,y); 114 ans+=chaxun(1,1,n,id[x],id[y]); 115 return ans?ans:1; 116 } 117 int main() 118 { 119 int m,a,b,c; 120 cin>>n>>m;char caozuo[5]; 121 for (int i=1;i<=n;i++) scanf("%d",&ys[i]); 122 for (int i=1;i<n;i++) { 123 scanf("%d%d",&a,&b);jia(a,b);jia(b,a); 124 } 125 dfs1(1,0,1);dfs2(1,1);jianshu(1,1,n); 126 while (m--) { 127 scanf("%s",caozuo); 128 scanf("%d%d",&a,&b); 129 switch (caozuo[0]) { 130 case ‘C‘:scanf("%d",&c); 131 ranse(a,b,c);break; 132 default: 133 134 printf("%d\n",xunwen(a,b));break; 135 } 136 } 137 //zhu wo zao dian AC!!! 138 return 0; 139 }
ok!!!