题目传送门
呵呵呵。
解法:
没学过树剖看这里
很水很水的树剖?
整段取反就打个lazy嘛。
列举各种情况。
就会发现,取反时:
最大值等于原来最小值取反,最小值等于原来最大值取反。
其他维护最大值最小值和就没什么了吧。
代码实现:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node {int x,y,next;}a[51000];int len,last[21000];
void ins(int x,int y) {len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int n,fa[21000],dep[21000],tot[21000],son[21000];
void pre_tree_node(int x) {
son[x]=0;tot[x]=1;
for(int k=last[x];k;k=a[k].next) {
int y=a[k].y;
if(y!=fa[x]) {
dep[y]=dep[x]+1;fa[y]=x;pre_tree_node(y);
if(tot[y]>tot[son[x]])son[x]=y;tot[x]+=tot[y];
}
}
}
int z,ys[21000],top[21000];
void pre_tree_edge(int x,int tp) {
ys[x]=++z;top[x]=tp;
if(son[x]!=0)pre_tree_edge(son[x],tp);
for(int k=last[x];k;k=a[k].next) {int y=a[k].y;if(fa[x]!=y&&son[x]!=y)pre_tree_edge(y,y);}
}
struct trnode {int l,r,lc,rc,c,mn,mx,lazy;}tr[51000];int trlen;
void bt(int l,int r) {
int now=++trlen;tr[now].l=l;tr[now].r=r;tr[now].c=tr[now].mx=tr[now].mn=0;tr[now].lc=tr[now].rc=-1;tr[now].lazy=0;
if(l<r) {int mid=(l+r)/2;tr[now].lc=trlen+1;bt(l,mid);tr[now].rc=trlen+1;bt(mid+1,r);}
}
void update(int now) {
int lc=tr[now].lc,rc=tr[now].rc;tr[now].lazy=0;
tr[lc].lazy^=1;tr[rc].lazy^=1;
int t=tr[lc].mx;tr[lc].mx=tr[lc].mn*-1;tr[lc].mn=t*-1;
t=tr[rc].mx;tr[rc].mx=tr[rc].mn*-1;tr[rc].mn=t*-1;
tr[lc].c*=-1;tr[rc].c*=-1;
}
int find_sum(int now,int l,int r) {
if(tr[now].lazy)update(now);
if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)return find_sum(lc,l,r);else if(l>mid)return find_sum(rc,l,r);
else return find_sum(lc,l,mid)+find_sum(rc,mid+1,r);
}
int find_max(int now,int l,int r) {
if(tr[now].lazy)update(now);
if(tr[now].l==l&&tr[now].r==r)return tr[now].mx;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)return find_max(lc,l,r);else if(l>mid)return find_max(rc,l,r);
else return max(find_max(lc,l,mid),find_max(rc,mid+1,r));
}
int find_min(int now,int l,int r) {
if(tr[now].lazy)update(now);
if(tr[now].l==l&&tr[now].r==r)return tr[now].mn;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)return find_min(lc,l,r);else if(l>mid)return find_min(rc,l,r);
else return min(find_min(lc,l,mid),find_min(rc,mid+1,r));
}
void change(int now,int x,int k) {
if(tr[now].lazy)update(now);
if(tr[now].l==tr[now].r) {tr[now].c=tr[now].mn=tr[now].mx=k;return ;}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(x<=mid)change(lc,x,k);else change(rc,x,k);
tr[now].mx=max(tr[lc].mx,tr[rc].mx);tr[now].mn=min(tr[lc].mn,tr[rc].mn);tr[now].c=tr[lc].c+tr[rc].c;
}
void qf(int now,int l,int r) {
if(tr[now].l==l&&tr[now].r==r) {tr[now].lazy^=1;int t=tr[now].mx;tr[now].mx=tr[now].mn*-1;tr[now].mn=t*-1;tr[now].c*=-1;return ;}
if(tr[now].lazy)update(now);int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)qf(lc,l,r);else if(l>mid)qf(rc,l,r);
else {qf(lc,l,mid),qf(rc,mid+1,r);}
tr[now].mx=max(tr[lc].mx,tr[rc].mx);tr[now].mn=min(tr[lc].mn,tr[rc].mn);tr[now].c=tr[lc].c+tr[rc].c;
}
int solve_sum(int x,int y) {
int tx=top[x],ty=top[y],ans=0;
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
ans+=find_sum(1,ys[ty],ys[y]);y=fa[ty];ty=top[y];
}
if(x==y)return ans;
if(dep[x]>dep[y])swap(x,y);return ans+find_sum(1,ys[son[x]],ys[y]);
}
const int inf=999999999;
int solve_max(int x,int y) {
int tx=top[x],ty=top[y],ans=-inf;
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
ans=max(ans,find_max(1,ys[ty],ys[y]));y=fa[ty];ty=top[y];
}
if(x==y)return ans;
if(dep[x]>dep[y])swap(x,y);return max(ans,find_max(1,ys[son[x]],ys[y]));
}
int solve_min(int x,int y) {
int tx=top[x],ty=top[y],ans=inf;
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
ans=min(ans,find_min(1,ys[ty],ys[y]));y=fa[ty];ty=top[y];
}
if(x==y)return ans;
if(dep[x]>dep[y])swap(x,y);return min(ans,find_min(1,ys[son[x]],ys[y]));
}
void solve_qf(int x,int y) {
int tx=top[x],ty=top[y];
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
qf(1,ys[ty],ys[y]);y=fa[ty];ty=top[y];
}
if(x==y)return ;
if(dep[x]>dep[y])swap(x,y);qf(1,ys[son[x]],ys[y]);
}
struct edge {int x,y,c;}e[21000];
int main() {
int m;scanf("%d",&n);len=0;memset(last,0,sizeof(last));
for(int i=1;i<n;i++) {scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].c);e[i].x++;e[i].y++;ins(e[i].x,e[i].y);ins(e[i].y,e[i].x);}
fa[1]=0;dep[1]=0;pre_tree_node(1);z=0;pre_tree_edge(1,1);trlen=0;bt(1,z);
for(int i=1;i<n;i++) {if(dep[e[i].x]>dep[e[i].y])swap(e[i].x,e[i].y);change(1,ys[e[i].y],e[i].c);}
scanf("%d",&m);
for(int i=1;i<=m;i++) {
char s[5];int x,y;scanf("%s%d%d",s+1,&x,&y);
if(s[1]=='C')change(1,ys[e[x].y],y);
else if(s[1]=='N')solve_qf(++x,++y);
else if(s[1]=='S')printf("%d\n",solve_sum(++x,++y));
else if(s[2]=='A')printf("%d\n",solve_max(++x,++y));
else printf("%d\n",solve_min(++x,++y));
}
return 0;
}