
输入样例:
3 5 5 3 2 1 1 1 1 2 2 3 2 5 3 4 2 3 4 1 1 2 1 2 3 5 1 2 1 5 3 2 4 4 3 5 5 1 2 1 2 2 1 2 2 3 2 4 3 5 1 1 2 1 3 2 1 2 2 2 4 2 2 2 1 4 1 5 5 2 1 1 1 1 1 2 1 4 2 3 4 5 2 4 2 1 1 1 1 2 1 4 1 2 3 3 1 2 2 2 2
输出样例:
2 3 1 0 2 0 2 2 1 0
数据范围:

思路:
树剖,动态开点,线段树
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 100500
using namespace std;
inline int read() {
int x = 0,f = 1;
char s = getchar();
while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
return x * f;
}
int T,n,m;
int head[N * 2],cnt,pos;
struct node { int nxt,to; }e[N * 2];
int tpos[N],top[N],fa[N],wson[N];
int size[N],dep[N],tot,a[N],root[200];
struct tree {
int l,r,num;
}tr[N * 400];
inline void cp(int u,int v) {
cnt ++;
e[cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
inline void dfs1(int u,int f)
{
size[u] = 1;
for(int i = head[u]; i ; i = e[i].nxt) {
int v = e[i].to;
if(v == f) continue;
fa[v] = u; dep[v] = dep[u] + 1;
dfs1(v,u); size[u] += size[v];
if(size[v] > size[wson[u]]) wson[u] = v;
}
}
inline void dfs2(int u,int Top) {
tpos[u] = ++ tot;
top[u] = Top;
if(wson[u]) dfs2(wson[u],Top);
for(int i = head[u]; i ; i = e[i].nxt) {
int v = e[i].to;
if(v == wson[u] || v == fa[u]) continue;
dfs2(v,v);
}
}
inline void update(int k)
{
tr[k].num = tr[tr[k].l].num + tr[tr[k].r].num;
}
inline void change(int &k,int l,int r,int x,int y) {
if(!k) k = ++ pos;
if(l == r) {
tr[k].num = y;
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) change(tr[k].l,l,mid,x,y);
if(x > mid) change(tr[k].r,mid + 1,r,x,y);
update(k);
}
inline int ask(int k,int l,int r,int a,int b) {
if(!k) return 0;
if(l >= a && r <= b) return tr[k].num;
int mid = (l + r) >> 1,res = 0;
if(a <= mid) res += ask(tr[k].l,l,mid,a,b);
if(b > mid) res += ask(tr[k].r,mid + 1,r,a,b);
return res;
}
inline int tr_ask(int u,int v,int col) {
int res = 0;
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u,v);
res += ask(root[col],1,n,tpos[top[u]],tpos[u]);
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u,v);
res += ask(root[col],1,n,tpos[u],tpos[v]);
return res;
}
inline void delldate(int k) {
tr[k].num = (tr[tr[k].l].num + tr[tr[k].r].num);
tr[k].l = tr[k].r = 0;
}
inline void dell(int k,int l,int r) {
if(!k) return ;
if(l == r) {
tr[k].num = 0;
return ;
}
int mid = (l + r) >> 1;
dell(tr[k].l,l,mid); dell(tr[k].r,mid + 1,r);
delldate(k);
}
inline void Work() {
n = read(); m = read();
for(int i = 1;i <= n;i ++) a[i] = read();
for(int i = 1;i <= n - 1;i ++) {
int a = read(),b = read();
cp(a,b),cp(b,a);
}
fa[1] = 1,dep[1] = 1;
dfs1(1,-1);
dfs2(1,1);
for(int i = 1;i <= n;i ++)change(root[a[i]],1,n,tpos[i],1);
for(int i = 1;i <= m;i ++) {
int tmp = read();
if(tmp == 1)
{
int u = read(),x = read();
change(root[a[u]],1,n,tpos[u],0);
a[u] = x;
change(root[a[u]],1,n,tpos[u],1);
}
if(tmp == 2)
{
int u = read(),v = read(),x = read();
printf("%d\n",tr_ask(u,v,x));
}
}
}
inline void Clean() {
for(int i = 1;i <= 110;i ++)dell(root[i],1,n),root[i] = 0;
memset(head,0,sizeof(head));
memset(fa,0,sizeof(fa));
memset(tpos,0,sizeof(tpos));
memset(top,0,sizeof(top));
memset(wson,0,sizeof(wson));
memset(size,0,sizeof(size));
memset(dep,0,sizeof(dep));
cnt = tot = pos = 0;
}
int main() {
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
T = read();
while(T --)
{
Work();
Clean();
}
return 0;
}
完毕--yilin