题意:给你一棵树,点带权,支持三种操作:单点修改;询问链上和;询问链上max。
这里的Query操作用了与上一题不太一样的做法(上一题用那种做法,因为在边带权的情况下换根太困难啦):
先ChangeRoot(U),然后Access(V),再Splay(V),询问V在辅助树中的左子树。
因为Splay的pushdown用了极为暴力的做法……故而跑得比原来写的链剖线段树慢一倍。不过常数不在意了。
#include<cstdio> #include<iostream> #include<stack> #include<cstring> #include<algorithm> using namespace std; #define maxn 30005 int fa[maxn],c[maxn][2],siz[maxn]; bool is_root[maxn],delta[maxn]; int val[maxn],totalval[maxn],maxv[maxn]; void Mark(int x){ if(x){ delta[x]^=1; } } void Maintain(int x) { siz[x]=siz[c[x][0]]+siz[c[x][1]]+1; totalval[x]=totalval[c[x][0]]+totalval[c[x][1]]+val[x]; maxv[x]=val[x]; if(c[x][0]){ maxv[x]=max(maxv[x],maxv[c[x][0]]); } if(c[x][1]){ maxv[x]=max(maxv[x],maxv[c[x][1]]); } } void pushdown(int x){ if(delta[x]){ Mark(c[x][0]); Mark(c[x][1]); swap(c[x][0],c[x][1]); delta[x]=0; } } void Rotate(int x,bool flag) { int y=fa[x]; c[y][!flag]=c[x][flag]; if(c[x][flag]){ fa[c[x][flag]]=y; } if(fa[y] && c[fa[y]][c[fa[y]][1]==y]==y){ c[fa[y]][c[fa[y]][1]==y]=x; } fa[x]=fa[y]; c[x][flag]=y; fa[y]=x; if(is_root[y]){ is_root[y]=0; is_root[x]=1; } Maintain(y); Maintain(x); } stack<int>st; void Splay(int x) { pushdown(x); if(!x || is_root[x]){ return; } int U=x; while(!is_root[U]){ st.push(U); U=fa[U]; } st.push(U); while(!st.empty()){ pushdown(st.top()); st.pop(); } int y; while(y=fa[x],(!is_root[x])){ if(is_root[y]){ Rotate(x,c[y][0]==x); } else{ if((c[y][0]==x)==(c[fa[y]][0]==y)){ Rotate(y,c[fa[y]][0]==y); } else{ Rotate(x,c[y][0]==x); y=fa[x]; } Rotate(x,c[y][0]==x); } } Maintain(x); } void Access(int x){ int y; Splay(x); while(fa[x]){ y=fa[x]; Splay(y); Splay(x); if(c[y][1]){ is_root[c[y][1]]=1; } is_root[x]=0; c[y][1]=x; Splay(x); } if(c[x][1]){ is_root[c[x][1]]=1; c[x][1]=0; } } void ChangeRoot(int x){ Access(x); Splay(x); Mark(x); } int QSum(int U,int V){ ChangeRoot(U); Access(V); Splay(V); return val[V]+totalval[c[V][0]]; } int QMax(int U,int V){ ChangeRoot(U); Access(V); Splay(V); if(!c[V][0]){ return val[V]; } else{ return max(val[V],maxv[c[V][0]]); } } int n,m; int v[maxn<<1],nex[maxn<<1],first[maxn],e; void AddEdge(int U,int V){ v[++e]=V; nex[e]=first[U]; first[U]=e; } int a[maxn]; void dfs(int U){ siz[U]=1; is_root[U]=1; val[U]=totalval[U]=maxv[U]=a[U]; for(int i=first[U];i;i=nex[i]){ if(!siz[v[i]]){ fa[v[i]]=U; dfs(v[i]); } } } int main(){ // freopen("bzoj1036.in","r",stdin); char op[10]; int x,y; scanf("%d",&n); for(int i=1;i<n;++i){ scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } for(int i=1;i<=n;++i){ scanf("%d",&a[i]); } dfs(1); scanf("%d",&m); for(int i=1;i<=m;++i){ scanf("%s%d%d",op,&x,&y); if(op[3]=='N'){ Splay(x); val[x]=y; Maintain(x); } else if(op[3]=='M'){ printf("%d ",QSum(x,y)); } else{ printf("%d ",QMax(x,y)); } } return 0; }