题意:给出一棵树,(1)路径加一个值;(2)路径上的节点的值反转(只是值反转,不是节点反转);(3)询问路径最大值 最小值 和。
解题思路:
题目简单,代码冗长
写这道题的时候还没有学LCT,所以我写了一种非常奇葩的方法,纯splay+树链剖分,代码冗长,但我觉得还挺好理解的。
首先我们可以先对整棵树进行树链剖分,分出轻重链之后就可以将一条链分解成若干条重链,用splay维护剖分出来的序列,查找最大最小和sum都是splay的基础操作就不说了,最关键的是进行树链翻转。这里的确让我为难了许久,后来我奇葩的想出了一个办法::将链按顺序提取出来合并然后进行反转再拆开按顺序放回去,这样就可以做到下一次查询这里正好是反过来的了,然后就是怎么做的问题了,这里的确变态,为了不改变点在序列的位置方便提取,我先按照这些条链在序列中从后往前提取,最后还要从前往后放回去,不过这里处理完之后就问题不大了,看着代码都是泪啊!!!
(代码核能,想看的话请做好心理准备)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
#include<iomanip>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
struct splay
{
splay *ls,*rs,*fa;
long long sum,maxx,minn,v,size;
long long lazy_mark;
bool rev_mark;
splay(long long x);
void push_up();
void push_down();
void add(long long x);
void rev();
}*null=new splay(2000209123),*root,*midroot,*swz[100005];
long long t;
long long pou[100000];
long long fir[100005];
long long nex[100005];
long long wz[100000];
struct point
{
long long top,son,fa,size,deep;
}a[100005];
struct bian
{
long long l,r;
}b[100005];
void dfs1(int u,int fro)
{
a[u].size=1;
a[u].deep=a[fro].deep+1;
for(int o=fir[u];o!=0;o=nex[o])
{
if(b[o].r!=fro)
{
a[b[o].r].fa=u;
dfs1(b[o].r,u);
a[u].size+=a[b[o].r].size;
if(a[b[o].r].size>a[a[u].son].size) a[u].son=b[o].r;
}
}
}
void dfs2(int u,int fro)
{
pou[++t]=u;
wz[u]=t;
if(u==a[a[u].fa].son) a[u].top=a[a[u].fa].top;
else a[u].top=u;
if(a[u].son) dfs2(a[u].son,u);
for(int o=fir[u];o!=0;o=nex[o])
{
if(b[o].r!=fro && b[o].r!=a[u].son) dfs2(b[o].r,u);
}
}
splay :: splay(long long x)
{
ls=rs=fa=null;
sum=maxx=minn=v=x;
lazy_mark=rev_mark=0;
size=null ? 1 : 0;
}
void splay :: add(long long x)
{
if(this==null) return;
lazy_mark+=x;
push_down();
}
void splay :: rev()
{
if(this==null) return;
rev_mark^=1;
push_down();
}
void splay :: push_up()
{
if(ls!=null) ls->push_down();
if(rs!=null) rs->push_down();
size=ls->size+rs->size+1;
maxx=0;
if(ls->maxx>maxx && ls!=null && ls->v!=2000209123) maxx=ls->maxx;
if(rs->maxx>maxx && rs!=null && rs->v!=2000209123) maxx=rs->maxx;
if(v>maxx) maxx=v;
minn=2147483647;
if(ls->minn<minn && ls!=null && ls->v!=2000209123) minn=ls->minn;
if(rs->minn<minn && rs!=null && rs->v!=2000209123) minn=rs->minn;
if(v<minn) minn=v;
sum=v;
if(ls->v!=2000209123 && ls!=null) sum+=ls->sum;
if(rs->v!=2000209123 && rs!=null) sum+=rs->sum;
}
void splay :: push_down()
{
if(rev_mark)
{
swap(ls,rs);
rev_mark=0;
if(ls!=null && ls->v!=2000209123) ls->rev_mark^=1;
if(rs!=null && rs->v!=2000209123) rs->rev_mark^=1;
}
if(lazy_mark)
{
v+=lazy_mark;
minn+=lazy_mark;
maxx+=lazy_mark;
sum+=lazy_mark*size;
if(ls!=null && ls->v!=2000209123) ls->lazy_mark+=lazy_mark;
if(rs!=null && rs->v!=2000209123) rs->lazy_mark+=lazy_mark;
lazy_mark=0;
}
}
void left(splay *x)
{
splay *y=x->fa;
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
x->fa=y->fa;
if(y==y->fa->ls) y->fa->ls=x;
else if(y==y->fa->rs) y->fa->rs=x;
y->fa=x;
y->push_up();
if(y==root) root=x;
}
void right(splay *x)
{
splay *y=x->fa;
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
x->fa=y->fa;
if(y==y->fa->ls) y->fa->ls=x;
else if(y==y->fa->rs) y->fa->rs=x;
y->fa=x;
y->push_up();
if(y==root) root=x;
}
void splaying(splay *x,splay *goal)
{
while(1)
{
splay *y=x->fa;
splay *z=y->fa;
if(y==goal) break;
if(z==goal)
{
if(x==y->ls) right(x);
else left(x);
break;
}
if(x==y->ls)
{
if(y==z->ls) right(y);
right(x);
}
else
{
if(y==z->rs) left(y);
left(x);
}
}
x->push_up();
}
void my_find(splay *x,long long mc,splay *z)
{
while(1)
{
x->push_down();
if(mc<=x->ls->size) x=x->ls;
else
{
mc-=x->ls->size;
if(mc==1) break;
mc--;
x=x->rs;
}
}
splaying(x,z);
midroot=x;
}
void add()
{
long long x,y,v;
scanf("%lld%lld%lld",&x,&y,&v);
while(a[x].top!=a[y].top)
{
if(a[a[x].top].deep<a[a[y].top].deep) swap(x,y);
my_find(root,wz[a[x].top],null);
my_find(root,wz[x]+2,root);
root->rs->ls->add(v);
x=a[a[x].top].fa;
}
if(a[x].deep<a[y].deep) swap(x,y);
my_find(root,wz[y],null);
my_find(root,wz[x]+2,root);
root->rs->ls->add(v);
root->rs->push_up();
root->push_up();
}
splay* maketree(long long l,long long r)
{
if(l>r) return null;
long long mid=l+r>>1;
splay *sp=new splay(0);
sp->ls=maketree(l,mid-1);
sp->rs=maketree(mid+1,r);
sp->ls->fa=sp->rs->fa=sp;
sp->push_up();
swz[mid]=sp;
return sp;
}
void init()
{
root=new splay(2000209123);
root->rs=new splay(2000209123);
root->rs->fa=root;
root->rs->ls=maketree(1,t);
root->rs->ls->fa=root->rs;
root->rs->push_up();
root->push_up();
}
int find_lca(int x,int y)
{
while(a[x].top!=a[y].top)
{
if(a[a[x].top].deep<a[a[y].top].deep) swap(x,y);
x=a[a[x].top].fa;
}
if(a[x].deep<a[y].deep) swap(x,y);
return y;
}
void my_merge(splay* x,splay* y)
{
my_find(x,x->size,null);
midroot->rs=y;
y->fa=midroot;
midroot->push_up();
}
splay* tiqu(int l,int r,splay* &o)
{
my_find(o,l,null);
my_find(o,r+2,root);
splay *mid=o->rs->ls;
mid->fa=null;
o->rs->ls=null;
o->rs->push_up();
o->push_up();
return mid;
}
struct tiquchulaide
{
int num,shou,len;
splay* ti,*newti;
}midd[50000];
bool cmp1(tiquchulaide a,tiquchulaide b)
{
return a.num<b.num;
}
bool cmp2(tiquchulaide a,tiquchulaide b)
{
return a.shou>b.shou;
}
bool cmp3(tiquchulaide a,tiquchulaide b)
{
return a.shou<b.shou;
}
int shou[50000];
int len[50000];
int top=0;
void y_find(int y,int lca)
{
if(y==lca) return;
if(a[y].top==a[lca].top)
{
shou[++top]=wz[lca]+1;
len[top]=wz[y]-wz[lca];
midd[top].num=top;
midd[top].shou=shou[top];
midd[top].len=len[top];
return;
}
y_find(a[a[y].top].fa,lca);
shou[++top]=wz[a[y].top];
len[top]=wz[y]-wz[a[y].top]+1;
midd[top].num=top;
midd[top].shou=shou[top];
midd[top].len=len[top];
}
void fanzhuanqujian()
{
long long jilu=0;
long long x,y;
scanf("%lld%lld",&x,&y);
top=0;
long long lca=find_lca(x,y);
while(x!=lca)
{
if(a[x].top==a[lca].top)
{
shou[++top]=wz[lca];
len[top]=wz[x]-wz[lca]+1;
midd[top].num=top;
midd[top].shou=shou[top];
midd[top].len=len[top];
break;
}
shou[++top]=wz[a[x].top];
len[top]=wz[x]-wz[a[x].top]+1;
midd[top].num=top;
midd[top].shou=shou[top];
midd[top].len=len[top];
x=a[a[x].top].fa;
}
jilu=top;
if(x==lca)
{
shou[++top]=wz[lca];
midd[top].shou=wz[lca];
midd[top].len=1;
midd[top].num=top;
len[top]=1;
}
y_find(y,lca);
sort(midd+1,midd+1+top,cmp2);
for(int i=1;i<=top;i++)
{
midd[i].ti=tiqu(midd[i].shou,midd[i].shou+midd[i].len-1,root);
if(midd[i].num<=jilu) midd[i].ti->rev();
}
sort(midd+1,midd+1+top,cmp1);
midroot=null;
for(int i=1;i<=top;i++)
{
//cout<<midroot->size<<" ";
if(midroot==null) midroot=midd[i].ti;
else my_merge(midroot,midd[i].ti);
}
//cout<<midroot->size<<endl;
midroot->rev();
for(int i=1;i<=top;i++)
{
//cout<<midroot->size<<endl;
my_find(midroot,midd[i].len,null);
//cout<<midd[i].shou<<" "<<midd[i].len<<endl;
splay *middd=midroot->rs;
middd->fa=null;
midroot->rs=null;
midroot->push_up();
midd[i].newti=midroot;
if(midd[i].num<=jilu) midd[i].newti->rev();
midroot=middd;
}
sort(midd+1,midd+1+top,cmp3);
for(int i=1;i<=top;i++)
{
my_find(root,midd[i].shou,null);
my_find(root,midd[i].shou+1,root);
root->rs->ls=midd[i].newti;
root->rs->ls->fa=root->rs;
root->rs->push_up();
root->push_up();
}
}
void sum()
{
long long x,y;
scanf("%lld%lld",&x,&y);
long long ans=0;
while(a[x].top!=a[y].top)
{
if(a[a[x].top].deep<a[a[y].top].deep) swap(x,y);
my_find(root,wz[a[x].top],null);
my_find(root,wz[x]+2,root);
ans+=root->rs->ls->sum;
x=a[a[x].top].fa;
}
if(a[x].deep<a[y].deep) swap(x,y);
my_find(root,wz[y],null);
my_find(root,wz[x]+2,root);
ans+=root->rs->ls->sum;
printf("%lld\n",ans);
}
void major()
{
long long maxx=-214748364700000000ll;
long long x,y;
scanf("%d%d",&x,&y);
long long ans=0;
while(a[x].top!=a[y].top)
{
if(a[a[x].top].deep<a[a[y].top].deep) swap(x,y);
my_find(root,wz[a[x].top],null);
my_find(root,wz[x]+2,root);
if(root->rs->ls->maxx>maxx) maxx=root->rs->ls->maxx;
x=a[a[x].top].fa;
}
if(a[x].deep<a[y].deep) swap(x,y);
my_find(root,wz[y],null);
my_find(root,wz[x]+2,root);
if(root->rs->ls->maxx>maxx) maxx=root->rs->ls->maxx;
printf("%lld\n",maxx);
}
void minor()
{
long long minn=214748364700000000ll;
long long x,y;
scanf("%lld%lld",&x,&y);
long long ans=0;
while(a[x].top!=a[y].top)
{
if(a[a[x].top].deep<a[a[y].top].deep) swap(x,y);
my_find(root,wz[a[x].top],null);
my_find(root,wz[x]+2,root);
if(root->rs->ls->minn<minn) minn=root->rs->ls->minn;
x=a[a[x].top].fa;
}
if(a[x].deep<a[y].deep) swap(x,y);
my_find(root,wz[y],null);
my_find(root,wz[x]+2,root);
if(root->rs->ls->minn<minn) minn=root->rs->ls->minn;
printf("%lld\n",minn);
}
char s[10];
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
long long n,m,r;
scanf("%lld%lld%lld",&n,&m,&r);
for(int i=1;i<n;i++)
{
scanf("%d%d",&b[i].l,&b[i].r);
b[n+i].l=b[i].r;
b[n+i].r=b[i].l;
nex[i]=fir[b[i].l];
fir[b[i].l]=i;
nex[n+i]=fir[b[i].r];
fir[b[i].r]=n+i;
}
int t=rand()%n+1;
dfs1(t,0);
dfs2(t,0);
init();
//for(int i=1;i<=t;i++) cout<<wz[i]<<" ";
for(int k=1;k<=m;k++)
{
scanf("%s",s);
if(s[2]=='c') add();
if(s[2]=='m') sum();
if(s[2]=='j') major();
if(s[2]=='n') minor();
if(s[2]=='v') fanzhuanqujian();
}
return 0;
}