清北学堂-计树-树剖-动态开点
作者:互联网
输入样例:
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
标签:树剖,int,res,tr,mid,计树,num,inline,清北 来源: https://www.cnblogs.com/yelir/p/11360515.html