传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3159
思路:题解与标程在此:http://tieba.baidu.com/p/2307619154
首先链翻转显然不能直接在lct上打翻转标记,那样是在翻转链的深度,不是翻转链上的值
于是就有了一种做法,写两个splay,一个维护权值,一个维护形态
每棵形态splay和对应值splay总保证点数相同,这样对于权值翻转我们就可以只在值splay上翻转,形态splay不变即可
关键是维护形态splay到值splay的指针
最重要的一点就是维护形态splay的根到对应值splay的根的指针
题解已经讲的比较清楚了,但是具体细节比较多
主要是在access的同时维护这个指针(因为access会导致splay的分离和合并,一定要想清楚)
形态splay执行splay操作时也要记得把原来根的指针传递给现在splay上来的新根
总之就是各种错,各种坑,改了不下十个错误才改对
另外我怎么觉得跨过LCA的链也是可以翻转的,这可是动态树啊,makeroot一下,access一下不就提出了这个链吗,代码不会有任何区别。也许是有不为人知的阴谋
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ls ch[x][0]
#define rs ch[x][1]
const int maxn=100010,maxm=maxn<<1;
typedef long long ll;
using namespace std;
int n,R,cas,Q,pre[maxm],now[maxn],son[maxm],tot;char op[12];
void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
struct Tsplay{
int siz[maxn],ch[maxn][2],fa[maxn],tag[maxn];ll mins[maxn],maxs[maxn],sum[maxn],val[maxn];bool rev[maxn];
int isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
int which(int x){return ch[fa[x]][1]==x;}
void init(int x,int v){siz[x]=1,mins[x]=maxs[x]=sum[x]=val[x]=v;}
void update(int x){
siz[x]=1,mins[x]=maxs[x]=sum[x]=val[x];
if (ls) siz[x]+=siz[ls],mins[x]=min(mins[x],mins[ls]),maxs[x]=max(maxs[x],maxs[ls]),sum[x]+=sum[ls];
if (rs) siz[x]+=siz[rs],mins[x]=min(mins[x],mins[rs]),maxs[x]=max(maxs[x],maxs[rs]),sum[x]+=sum[rs];
}
void add(int x,int v){if (x) sum[x]+=1ll*v*siz[x],tag[x]+=v,mins[x]+=v,maxs[x]+=v,val[x]+=v;}
void rever(int x){swap(ls,rs),rev[x]^=1;}
void down(int x){
if (tag[x]) add(ls,tag[x]),add(rs,tag[x]),tag[x]=0;
if (rev[x]) rever(ls),rever(rs),rev[x]=0;
}
int relax(int x){
int anc=isroot(x)?x:relax(fa[x]);
down(x);return anc;
}
void rotate(int x){
int y=fa[x],z=fa[y],nx=which(x),ny=which(y);
fa[ch[x][!nx]]=y,ch[y][nx]=ch[x][!nx];
fa[x]=z;if (!isroot(y)) ch[z][ny]=x;//这行要放在下一行前,不然isroot会错
fa[y]=x,ch[x][!nx]=y;update(y);
}
void splay(int x){
relax(x);
while(!isroot(x)){
int y=fa[x];
if (isroot(y)) rotate(x);
else if (which(x)==which(y)) rotate(y),rotate(x);
else rotate(x),rotate(x);
}
update(x);
}
int findrt(int &x){while (fa[x]) x=fa[x];return x;}
int find(int &x,int rank){
for (;;){
down(x);
if (rank<=siz[ls]) x=ls;
else if (rank==siz[ls]+1) return x;
else rank-=(siz[ls]+1),x=rs;
}
}
}val;
struct Tlct{
int siz[maxn],ch[maxn][2],fa[maxn],rt[maxn],q[maxn];bool rev[maxn];
int isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
int which(int x){return ch[fa[x]][1]==x;}
void init(int x,int v,int ff){rt[x]=x,siz[x]=1,fa[x]=ff,val.init(x,v);}
void update(int x){siz[x]=siz[ls]+siz[rs]+1;}
void rever(int x){swap(ls,rs),rev[x]^=1;}
void down(int x){if (rev[x]) rever(ls),rever(rs),rev[x]=0;}
int relax(int x){
int anc=isroot(x)?x:relax(fa[x]);
down(x);return anc;
}
void rotate(int x){
int y=fa[x],z=fa[y],nx=which(x),ny=which(y);
fa[ch[x][!nx]]=y,ch[y][nx]=ch[x][!nx];
fa[x]=z;if (!isroot(y)) ch[z][ny]=x;
fa[y]=x,ch[x][!nx]=y;update(y);
}
void splay(int x){
int anc=relax(x);
rt[x]=rt[anc];
while(!isroot(x)){
int y=fa[x];
if (isroot(y)) rotate(x);
else if (which(x)==which(y)) rotate(y),rotate(x);
else rotate(x),rotate(x);
}
update(x);
}
void access(int x){
for (int y=0;x;y=x,x=fa[x]){
splay(x);int x2=val.findrt(rt[x]);int y2=val.findrt(rt[y]);
if (!y) y2=0;//这句特判一定要加,因为rt【0】会被改动
val.find(x2,siz[ls]+1),val.splay(x2),rt[x]=x2;
rt[rs]=val.ch[x2][1],val.fa[val.ch[x2][1]]=0,val.ch[x2][1]=y2,val.fa[y2]=x2,val.update(x2);
rs=y,update(x);
}
}
void makeroot(int x){access(x),splay(x),rever(x),val.rever(rt[x]);}
void split(int x,int y){makeroot(x),access(y);}
void dfs(int x,int ff){
init(x,0,ff);
for (int y=now[x];y;y=pre[y])
if (son[y]!=ff) dfs(son[y],x);
}
}lct;
int main(){
scanf("%d%d%d",&n,&Q,&R);
for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
lct.dfs(R,0);
for (int i=1,x,y,z;i<=Q;i++){
scanf("%s%d%d",op+1,&x,&y);
lct.split(x,y);int vy=val.findrt(lct.rt[y]);//SB错误,y打成x
if (op[3]=='c') scanf("%d",&z),val.add(vy,z);
else if (op[3]=='m') printf("%lld\n",val.sum[vy]);
else if (op[3]=='j') printf("%lld\n",val.maxs[vy]);
else if (op[3]=='n') printf("%lld\n",val.mins[vy]);
else val.rever(vy);
}
return 0;
}