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;
}