肯定是树链剖分的题啦
树剖怎么做可以看我上一篇博客
如果我们已经剖完了:
然后考虑怎么维护重链和查询
用线段树维护的时候当前区间的区间颜色个数应该等于左儿子+右儿子,但是当左儿子的右端点和右儿子的左端点颜色一样,显然区间数要减1
所以每个节点存一下左端点的右端点颜色正常维护即可
考虑查询,在同一重链上的点显然线段树可以解决,当top[u]!=top[v]的时候,得让deep较深的爬树,那么答案就要+=爬树那一段的区间个数
但是有可能的是fa[top[u]]的颜色和top[u]的颜色相等,这个时候需要答案--,这样才能保证下次爬树的时候不会多算
注意:请写单点查询询问颜色,因为fa[top[u]]和top[u]是轻链的两端,不能保证在线段树中编号连续,所以不能区间查询是否是个数是1
修改同理,爬树的时候修改即可
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define N 100010 5 using namespace std; 6 int n,m,head[N],indx[N],pos[N],fa[N],ecnt,color[N],deep[N],sz[N],top[N],a,b,c,tot,son[N]; 7 char s[N]; 8 int read() 9 { 10 int ret=0,neg=1; 11 char j=getchar(); 12 for (;j>'9' || j<'0';j=getchar()) 13 if (j == '-') neg=-1; 14 for (;j>='0' && j<='9';j=getchar()) 15 ret=ret*10+j-'0'; 16 return ret*neg; 17 } 18 struct adj 19 { 20 int nxt,v; 21 }e[2*N]; 22 struct node 23 { 24 int l,r,Lcolor,Rcolor,sum,lz; 25 }t[4*N]; 26 void add(int u,int v)//加边 27 { 28 e[++ecnt].v=v; 29 e[ecnt].nxt=head[u]; 30 head[u]=ecnt; 31 e[++ecnt].v=u; 32 e[ecnt].nxt=head[v]; 33 head[v]=ecnt; 34 } 35 void dfs1(int x,int father,int d)//第一次dfs 36 { 37 fa[x]=father,deep[x]=d,sz[x]=1; 38 for (int i=head[x];i;i=e[i].nxt) 39 { 40 int v=e[i].v; 41 if (v==father) continue; 42 dfs1(v,x,d+1); 43 sz[x]+=sz[v]; 44 if (sz[son[x]]<sz[v]) son[x]=v; 45 } 46 } 47 void dfs2(int x,int TOP)//第二次dfs 48 { 49 pos[x]=++tot; 50 indx[tot]=x; 51 top[x]=TOP; 52 if (son[x]) dfs2(son[x],TOP); 53 for (int i=head[x];i;i=e[i].nxt) 54 { 55 int v=e[i].v; 56 if (v==fa[x] || v==son[x]) continue; 57 if (v!=0) dfs2(v,v); 58 } 59 } 60 void pushup(int p)//线段树更新 61 { 62 t[p].sum=t[p<<1].sum+t[p<<1|1].sum; 63 if (t[p<<1].Rcolor==t[p<<1|1].Lcolor) t[p].sum--; 64 t[p].Lcolor=t[p<<1].Lcolor; 65 t[p].Rcolor=t[p<<1|1].Rcolor; 66 } 67 void pushdown(int p)//lazy下放 68 { 69 if (t[p].l==t[p].r || t[p].lz==-1) return; 70 int w=t[p].lz; 71 t[p<<1].Lcolor=t[p<<1].Rcolor=t[p<<1|1].Lcolor=t[p<<1|1].Rcolor=t[p<<1].lz=t[p<<1|1].lz=w; 72 t[p<<1].sum=t[p<<1|1].sum=1; 73 t[p].lz=-1; 74 } 75 void build(int p,int l,int r)//建树 76 { 77 t[p].l=l,t[p].r=r,t[p].lz=-1; 78 if (l==r) 79 { 80 t[p].Lcolor=t[p].Rcolor=color[indx[l]]; 81 t[p].sum=1; 82 } 83 else 84 { 85 int mid=l+r>>1; 86 build(p<<1,l,mid); 87 build(p<<1|1,mid+1,r); 88 pushup(p); 89 } 90 } 91 void modify(int p,int l,int r,int k)//区间修改 92 { 93 if (l==t[p].l && r==t[p].r) 94 { 95 t[p].sum=1; 96 t[p].Lcolor=t[p].Rcolor=k; 97 t[p].lz=k; 98 return; 99 } 100 pushdown(p); 101 int mid=t[p].l+t[p].r>>1; 102 if (r<=mid) 103 modify(p<<1,l,r,k); 104 else if (l>mid) modify(p<<1|1,l,r,k); 105 else 106 modify(p<<1,l,mid,k),modify(p<<1|1,mid+1,r,k); 107 pushup(p); 108 } 109 int query(int p,int l,int r)//区间询问 110 { 111 if (l==t[p].l && r==t[p].r) 112 return t[p].sum; 113 pushdown(p); 114 int mid=t[p].l+t[p].r>>1; 115 if (r<=mid) 116 return query(p<<1,l,r); 117 if (l>mid) return query(p<<1|1,l,r); 118 int tmp=query(p<<1,l,mid)+query(p<<1|1,mid+1,r); 119 if (t[p<<1].Rcolor==t[p<<1|1].Lcolor) tmp--; 120 return tmp; 121 } 122 int Qcolor(int p,int l)//单点询问 123 { 124 if (t[p].l==t[p].r && t[p].l==l) return t[p].Lcolor; 125 pushdown(p); 126 int mid=t[p].l+t[p].r>>1; 127 if (l<=mid) return Qcolor(p<<1,l); 128 else return Qcolor(p<<1|1,l); 129 } 130 void getcolor(int a,int b,int w)//修改 131 { 132 while (top[a]!=top[b])//爬树 133 { 134 if (deep[top[a]]<deep[top[b]]) swap(a,b); 135 modify(1,pos[top[a]],pos[a],w); 136 a=fa[top[a]]; 137 } 138 if (deep[a]>deep[b]) swap(a,b); 139 modify(1,pos[a],pos[b],w); 140 } 141 int querycolor(int u,int v)//询问 142 { 143 int ret=0; 144 while (top[u]!=top[v]) 145 { 146 if (deep[top[u]]<deep[top[v]]) swap(u,v); 147 ret+=query(1,pos[top[u]],pos[u]); 148 if (Qcolor(1,pos[fa[top[u]]])==Qcolor(1,pos[top[u]])) ret--;//看题解 149 u=fa[top[u]]; 150 } 151 if (deep[u]>deep[v]) swap(u,v); 152 return ret+query(1,pos[u],pos[v]); 153 } 154 int main() 155 { 156 n=read(),m=read(); 157 for (int i=1;i<=n;i++) 158 color[i]=read(); 159 for (int i=1;i<n;i++) 160 add(read(),read()); 161 dfs1(1,0,0); 162 dfs2(1,1); 163 build(1,1,n); 164 while (m--) 165 { 166 scanf("%s",s); 167 if (s[0]=='C') 168 { 169 a=read(),b=read(),c=read(); 170 getcolor(a,b,c); 171 } 172 else 173 { 174 scanf("%d%d",&a,&b); 175 printf("%d ",querycolor(a,b)); 176 } 177 } 178 return 0; 179 }