zoukankan      html  css  js  c++  java
  • 清北学堂-计树-树剖-动态开点

    输入样例:

    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
    ",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

  • 相关阅读:
    《JS权威指南学习总结--6.6属性getter和setter》
    《JS权威指南学习总结--6.5枚举属性》
    django的模板系统
    django额外参数的传递和url命名
    python在图片上画矩形
    当爬虫遇到js加密
    php基础-7
    php基础-6
    php基础-5
    php基础-4
  • 原文地址:https://www.cnblogs.com/yelir/p/11360515.html
Copyright © 2011-2022 走看看