luogu3313 [SDOI2014]旅行

对每一个宗教建一棵线段树,然后树剖搞搞

#include <iostream>
#include <cstdio>
using namespace std;
int n, m, w[100005], c[100005], uu, vv, hea[100005], cnt, dep[100005];
int fa[100005], top[100005], idx[100005], qaq, siz[100005], son[100005];
int rot[100005], orz, zdz[5000005], sum[5000005], lson[5000005];
int rson[5000005];
char ss[15];
struct Edge{
	int too, nxt, val;
}edge[200005];
void add_edge(int fro, int too){
	edge[++cnt].nxt = hea[fro];
	edge[cnt].too = too;
	hea[fro] = cnt;
}
void dfs1(int x, int f){
	fa[x] = f;
	siz[x] = 1;
	dep[x] = dep[f] + 1;
	int maxSon=-1;
	for(int i=hea[x]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(t!=f){
			dfs1(t, x);
			siz[x] += siz[t];
			if(maxSon<siz[t])	maxSon = siz[t], son[x] = t;
		}
	}
}
void dfs2(int x, int topf){
	top[x] = topf;
	idx[x] = ++qaq;
	if(!son[x])	return ;
	dfs2(son[x], topf);
	for(int i=hea[x]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(t!=fa[x] && t!=son[x])
			dfs2(t, t);
	}
}
void pushUp(int o){
	sum[o] = sum[lson[o]] + sum[rson[o]];
	zdz[o] = max(zdz[lson[o]], zdz[rson[o]]);
}
void insert(int &o, int l, int r, int x, int w){
	if(!o)	o = ++orz;
	if(l==r)	sum[o] = zdz[o] = w;
	else{
		int mid=(l+r)>>1;
		if(x<=mid)	insert(lson[o], l, mid, x, w);
		if(mid<x)	insert(rson[o], mid+1, r, x, w);
		pushUp(o);
	}
}
void clr(int &o){
	lson[o] = rson[o] = sum[o] = zdz[o] = 0;
	o = 0;
}
void shanchu(int &o, int l, int r, int x){
	if(l==r)	clr(o);
	else{
		int mid=(l+r)>>1;
		if(x<=mid)	shanchu(lson[o], l, mid, x);
		if(mid<x)	shanchu(rson[o], mid+1, r, x);
		pushUp(o);
		if(lson[o]+rson[o]==0)	clr(o);
	}
}
int querySGTSum(int o, int l, int r, int x, int y){
	if(!o)	return 0;
	if(l>=x && r<=y)	return sum[o];
	else{
		int mid=(l+r)>>1;
		int ans=0;
		if(x<=mid)	ans += querySGTSum(lson[o], l, mid, x, y);
		if(mid<y)	ans += querySGTSum(rson[o], mid+1, r, x, y);
		return ans;
	}
}
int querySGTMax(int o, int l, int r, int x, int y){
	if(!o)	return 0;
	if(l>=x && r<=y)	return zdz[o];
	else{
		int mid=(l+r)>>1;
		int ans=0;
		if(x<=mid)	ans = max(ans, querySGTMax(lson[o], l, mid, x, y));
		if(mid<y)	ans = max(ans, querySGTMax(rson[o], mid+1, r, x, y));
		return ans;
	}
}
int querySum(int uu, int vv){
	int bel=c[uu], ans=0;
	while(top[uu]!=top[vv]){
		if(dep[top[uu]]<dep[top[vv]])	swap(uu, vv);
		ans += querySGTSum(rot[bel], 1, n, idx[top[uu]], idx[uu]);
		uu = fa[top[uu]];
	}
	if(dep[uu]>dep[vv])	swap(uu, vv);
	ans += querySGTSum(rot[bel], 1, n, idx[uu], idx[vv]);
	return ans;
}
int queryMax(int uu, int vv){
	int bel=c[uu], ans=0;
	while(top[uu]!=top[vv]){
		if(dep[top[uu]]<dep[top[vv]])	swap(uu, vv);
		ans =max(ans, querySGTMax(rot[bel], 1, n, idx[top[uu]], idx[uu]));
		uu = fa[top[uu]];
	}
	if(dep[uu]>dep[vv])	swap(uu, vv);
	ans = max(ans, querySGTMax(rot[bel], 1, n, idx[uu], idx[vv]));
	return ans;
}
int main(){
	cin>>n>>m;
	for(int i=1; i<=n; i++)	scanf("%d %d", &w[i], &c[i]);
	for(int i=1; i<n; i++){
		scanf("%d %d", &uu, &vv);
		add_edge(uu, vv);
		add_edge(vv, uu);
	}
	dep[1] = 1; 
	dfs1(1, 0);
	dfs2(1, 1);
	for(int i=1; i<=n; i++)
		insert(rot[c[i]], 1, n, idx[i], w[i]);
	while(m--){
		scanf("%s %d %d", ss, &uu, &vv);
		if(ss[0]=='C' && ss[1]=='C'){
			shanchu(rot[c[uu]], 1, n, idx[uu]);
			c[uu] = vv;
			insert(rot[c[uu]], 1, n, idx[uu], w[uu]);
		}
		if(ss[0]=='C' && ss[1]=='W'){
			w[uu] = vv;
			insert(rot[c[uu]], 1, n, idx[uu], w[uu]);
		}
		if(ss[0]=='Q' && ss[1]=='S')
			printf("%d\n", querySum(uu, vv));
		if(ss[0]=='Q' && ss[1]=='M')
			printf("%d\n", queryMax(uu, vv));
	}
	return 0;
}
posted @ 2018-01-24 21:01  poorpool  阅读(163)  评论(0)    收藏  举报