QAQ
【题目分析】
一道裸的剖分被一个极度sb的错误卡了两天。。。。。。
题意很明显,维护5个操作:单点修改,区间取相反数,区间求和,区间求最大值,区间求最小值。
因为求一条路径,考虑树链剖分维护(注意dfs序时优先dfs重儿子!!!这样在线段树上的编号才连续!!!)
考虑第一个操作,对于一条路径,如果修改了他的权值,那么只会对深度较浅的一个点向下走、深度较深的向上走会产生影响,所以单点修改较深点权值。(见代码update1操作)
考虑第二个操作,就是区间交换最大值最小值、区间和最大值最小值取反即可(见代码push_now操作)
考虑第三、四、五个操作,直接在树剖的时候统计答案即可。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
const int MAXM=1e6+10;
const int INF=0x3f3f3f3f;
int n,m,cnt=1,tot;
int head[MAXN],fa[MAXN],top[MAXN],depth[MAXN],siz[MAXN],son[MAXN];
int a[MAXN],dfn[MAXN],ys[MAXN];
struct Edge{
int to,nxt,w;
}edge[MAXM];
struct node{
int l,r;
int sum,maxx,minn;
int tag;
}tr[MAXN<<2];
void push_up(int root)
{
tr[root].sum=tr[root<<1].sum+tr[root<<1|1].sum;
tr[root].maxx=max(tr[root<<1].maxx,tr[root<<1|1].maxx);
tr[root].minn=min(tr[root<<1].minn,tr[root<<1|1].minn);
}
void push_now(int root)
{
swap(tr[root].maxx,tr[root].minn);
tr[root].sum=-tr[root].sum;
tr[root].maxx=-tr[root].maxx;
tr[root].minn=-tr[root].minn;
tr[root].tag^=1;
}
void push_down(int root)
{
if(tr[root].tag)
{
push_now(root<<1);
push_now(root<<1|1);
tr[root].tag=0;
}
}
void build(int root,int l,int r)
{
tr[root].l=l;
tr[root].r=r;
if(l==r)
{
tr[root].sum=tr[root].maxx=tr[root].minn=a[ys[l]];
return ;
}
int mid=l+r>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
push_up(root);
}
void update1(int root,int l,int r,int x,int key)
{
if(l==r)
{
tr[root].sum=tr[root].maxx=tr[root].minn=key;
return ;
}
push_down(root);
int mid=l+r>>1;
if(x<=mid)
update1(root<<1,l,mid,x,key);
else
update1(root<<1|1,mid+1,r,x,key);
push_up(root);
}
void update2(int root,int l,int r,int L,int R)
{
if(L>r||R<l)
return ;
if(L<=l&&r<=R)
{
push_now(root);
return ;
}
push_down(root);
int mid=l+r>>1;
if(R<=mid)
update2(root<<1,l,mid,L,R);
else
{
if(L>mid)
update2(root<<1|1,mid+1,r,L,R);
else
update2(root<<1,l,mid,L,mid),update2(root<<1|1,mid+1,r,mid+1,R);
}
push_up(root);
}
int query_sum(int root,int l,int r,int L,int R)
{
if(l>R||r<L)
return 0;
if(L<=l&&r<=R)
return tr[root].sum;
push_down(root);
int mid=l+r>>1;
if(R<=mid)
return query_sum(root<<1,l,mid,L,R);
else
{
if(L>mid)
return query_sum(root<<1|1,mid+1,r,L,R);
else
return query_sum(root<<1,l,mid,L,mid)+query_sum(root<<1|1,mid+1,r,mid+1,R);
}
}
int query_max(int root,int l,int r,int L,int R)
{
if(l>R||r<L)
return -INF;
if(L<=l&&r<=R)
return tr[root].maxx;
push_down(root);
int mid=l+r>>1;
if(R<=mid)
return query_max(root<<1,l,mid,L,R);
else
{
if(L>mid)
return query_max(root<<1|1,mid+1,r,L,R);
else
return max(query_max(root<<1,l,mid,L,mid),query_max(root<<1|1,mid+1,r,mid+1,R));
}
}
int query_min(int root,int l,int r,int L,int R)
{
if(l>R||r<L)
return INF;
if(L<=l&&r<=R)
return tr[root].minn;
push_down(root);
int mid=l+r>>1;
if(R<=mid)
return query_min(root<<1,l,mid,L,R);
else
{
if(L>mid)
return query_min(root<<1|1,mid+1,r,L,R);
else
return min(query_min(root<<1,l,mid,L,mid),query_min(root<<1|1,mid+1,r,mid+1,R));
}
}
void add(int x,int y,int z)
{
cnt++;
edge[cnt].nxt=head[x];
head[x]=cnt;
edge[cnt].to=y;
edge[cnt].w=z;
}
inline void dfs1(int p)
{
siz[p]=1;
for(int u=head[p];u!=-1;u=edge[u].nxt)
{
int to=edge[u].to;
if(to==fa[p])
continue;
a[to]=edge[u].w,fa[to]=p,depth[to]=depth[p]+1;
dfs1(to);
siz[p]+=siz[to];
if(siz[to]>siz[son[p]])
son[p]=to;
}
}
inline void dfs2(int p,int tp)
{
top[p]=tp,ys[dfn[p]=++tot]=p;
if(!son[p])
return;
dfs2(son[p],tp);
for(int u=head[p];u!=-1;u=edge[u].nxt)
{
int to=edge[u].to;
if(to==fa[p]||to==son[p])
continue;
dfs2(to,to);
}
}
void change(int x,int y)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]])
swap(x,y);
update2(1,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(depth[x]<depth[y])
swap(x,y);
update2(1,1,n,dfn[y]+1,dfn[x]);
}
int find_sum(int x,int y)
{
int ret=0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]])
swap(x,y);
ret+=query_sum(1,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(depth[x]<depth[y])
swap(x,y);
return ret+query_sum(1,1,n,dfn[y]+1,dfn[x]);
}
int find_max(int x,int y)
{
int ret=-INF;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]])
swap(x,y);
ret=max(ret,query_max(1,1,n,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(depth[x]<depth[y])
swap(x,y);
return max(ret,query_max(1,1,n,dfn[y]+1,dfn[x]));
}
int find_min(int x,int y)
{
int ret=INF;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]])
swap(x,y);
ret=min(ret,query_min(1,1,n,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(depth[x]<depth[y])
swap(x,y);
return min(ret,query_min(1,1,n,dfn[y]+1,dfn[x]));
}
int find(int x)
{
return depth[edge[x<<1].to]>depth[edge[x<<1^1].to]?edge[x<<1].to:edge[x<<1^1].to;
}
int Read()
{
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int main()
{
memset(head,-1,sizeof(head));
n=Read();
for(int i=1;i<n;++i)
{
int x=Read()+1,y=Read()+1,z=Read();
add(x,y,z),add(y,x,z);
}
dfs1(1);
dfs2(1,1);
build(1,1,n);
m=Read();
while(m--)
{
char cz[5];
scanf("%s",cz);
int x=Read(),y=Read();
if(cz[0]=='C')
update1(1,1,n,dfn[find(x)],y);
if(cz[0]=='N')
change(x+1,y+1);
if(cz[0]=='S')
printf("%d\n",find_sum(x+1,y+1));
if(cz[1]=='A')
printf("%d\n",find_max(x+1,y+1));
if(cz[1]=='I')
printf("%d\n",find_min(x+1,y+1));
}
return 0;
}