LG 2590 树的统计

蒟蒻我一开始以为倍增搞搞即可
突然意识到修改……

emm,还是熟练剖分吧

#include <cstdio>
#include <cassert>

int read(){
	int x=0, f=1;char ch=getchar();
	while(ch<'0' || ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch>='0' && ch<='9'){x=x*10+(ch-'0');ch=getchar();}
	return x*f;
}

const int MAXN=30111;
const int MAXM=200111;
const long long LONF=4567891012345678910LL;

long long max(long long a, long long b){
	return (a>b)?a:b;
}

int N, M;

struct Vert{
	int FE;
	int Dep, Size;
	int Fa, Son, Top;
	int Dps, Dpr;
	long long Val;
} V[MAXN];

struct Edge{
	int x, y, next;
} E[MAXN<<1];

int Ecnt=0;

void addE(int a, int b){
	++Ecnt;
	E[Ecnt].x=a;E[Ecnt].y=b;E[Ecnt].next=V[a].FE;V[a].FE=Ecnt;
}

void DFS1(int at){
	V[at].Size=1;
	for(int k=V[at].FE, to;k>0;k=E[k].next){
		to=E[k].y;
		if(to==V[at].Fa)	continue;
		V[to].Fa=at;
		V[to].Dep=V[at].Dep+1;
		DFS1(to);
		V[at].Size+=V[to].Size;
		if(V[at].Son<=0 || V[to].Size>V[V[at].Son].Size)	V[at].Son=to;
	}
}

int Dfn[MAXN], DFN=0;

void DFS2(int at, int t){
	++DFN;Dfn[DFN]=at;
	V[at].Dps=DFN;
	V[at].Top=t;
	if(V[at].Son>0)	DFS2(V[at].Son, t);
	for(int k=V[at].FE, to;k>0;k=E[k].next){
		to=E[k].y;
		if(to==V[at].Fa || to==V[at].Son)	continue;
		DFS2(to, to);
	}
	V[at].Dpr=DFN;
}

struct Data{
	long long Sm, Mx;
	Data(long long _s=0LL, long long _m=-LONF){
		Sm=_s;Mx=_m;
	}
} ZERO;

Data operator + (Data a, Data b){
	return Data(a.Sm+b.Sm, max(a.Mx, b.Mx));
}

struct Node{
	int l, r;
	Data d;
} T[MAXN<<2];

int L, R;
long long op;

inline void pup(int &at){
	T[at].d=T[at<<1].d+T[(at<<1)|1].d;
}

void BuildTree(int l, int r, int at){
	T[at].l=l;T[at].r=r;
	int m=(l+r)>>1;
	if(l==r){
		T[at].d=Data(V[Dfn[m]].Val, V[Dfn[m]].Val);
		return;
	}
	BuildTree(l, m, at<<1);
	BuildTree(m+1, r, (at<<1)|1);
	pup(at);
}

inline void opr(int &at){
	T[at].d=Data(op, op);
}

void Update(int at){
	if(T[at].l>=L && T[at].r<=R){
		opr(at);
		return;
	}
	int m=(T[at].l+T[at].r)>>1;
	if(L<=m)	Update(at<<1);
	if(R>m)	Update((at<<1)|1);
	pup(at);
}

Data Ask(int at){
	if(T[at].l>=L && T[at].r<=R){
		return T[at].d;
	}
	int m=(T[at].l+T[at].r)>>1;
	Data ret=ZERO;
	if(L<=m)	ret=ret+Ask(at<<1);
	if(R>m)	ret=ret+Ask((at<<1)|1);
	return ret;
}

Data Ask_index(int a, int b){
	Data ret=ZERO;
	while(V[a].Top!=V[b].Top){
		if(V[V[a].Top].Dep>V[V[b].Top].Dep){
			L=V[V[a].Top].Dps;R=V[a].Dps;
			ret=ret+Ask(1);
			a=V[V[a].Top].Fa;
		}
		else{
			L=V[V[b].Top].Dps;R=V[b].Dps;
			ret=ret+Ask(1);
			b=V[V[b].Top].Fa;
		}
	}
	if(V[a].Dep>V[b].Dep){
		L=V[b].Dps;R=V[a].Dps;
		ret=ret+Ask(1);
	}
	else{
		L=V[a].Dps;R=V[b].Dps;
		ret=ret+Ask(1);
	}
	return ret;
}

int main(){
	
	N=read();
	for(int i=1, a, b;i<N;++i){
		a=read();b=read();
		addE(a, b);addE(b, a);
	}
	for(int i=1;i<=N;++i)	V[i].Val=read();
	
	V[1].Dep=1;
	DFS1(1);
	DFS2(1, 1);
	
	assert(DFN==N);
	BuildTree(1, N, 1);
	
	M=read();
	char com[111];
	Data ANS;
	for(int i=1, a, b, c;i<=M;++i){
		scanf("%s", com);
		if(com[0]=='C'){
			a=read();c=read();
			L=V[a].Dps;R=V[a].Dps;op=c;
			Update(1);
		}
		else{
			a=read();b=read();
			ANS=Ask_index(a, b);
			if(com[1]=='M'){
				printf("%lld\n", ANS.Mx);
			}
			if(com[1]=='S'){
				printf("%lld\n", ANS.Sm);
			}
		}
	}
	
	return 0;
}

posted @ 2018-05-28 11:38  Pickupwin  阅读(130)  评论(0编辑  收藏  举报