调了我一晚上
想法很好:http://ezreal-dn.com/archives/124
但是因为我作死 实现细节按照自己的习惯搞搞搞 结果WA到爆炸
总算是调出来了
#include
#include
#include
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=50005;
struct Splay{
struct node{
node *ch[2],*p,*fat; int idx;
int size,Max,Sum;
int w,add;
int tree,chadd;
bool dir() { return p->ch[1]==this; }
void setc(node *x,int d) { ch[d]=x; x->p=this; }
void update() {
size=ch[0]->size+ch[1]->size+1;
Max=max(max(ch[0]->Max,ch[1]->Max),w);
Sum=ch[0]->Sum+ch[1]->Sum+w;
}
void Mark(int v){
w+=v; Max+=v; Sum+=size*v; add+=v;
}
void CMark(int v){
tree+=v; chadd+=v;
}
void pushdown(node *null){
if (add){
if (ch[0]!=null) ch[0]->Mark(add);
if (ch[1]!=null) ch[1]->Mark(add);
add=0;
}
if (chadd){
if (ch[0]!=null) ch[0]->CMark(chadd);
if (ch[1]!=null) ch[1]->CMark(chadd);
chadd=0;
}
}
}Mem[N],*null;
Splay(){ null=Mem; null->p=null->ch[0]=null->ch[1]=null->fat=null; null->size=0; null->Max=-1<<30; null->Sum=0; }
inline void rot(node *x){
if (x==null || x->p==null) return;
bool d=x->dir(); node *p=x->p;
if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null;
p->setc(x->ch[d^1],d); x->setc(p,d^1); p->update(); x->update(); swap(x->fat,p->fat);
}
node *sta[N];
void splay(node *x){
int pnt=0; node *y=x;
while (y!=null) sta[++pnt]=y,y=y->p;
for (int i=pnt;i;i--) sta[i]->pushdown(null);
while (x->p!=null)
if (x->p->p==null)
rot(x);
else
x->dir()==x->p->dir()?(rot(x->p),rot(x)):(rot(x),rot(x));
}
node* Access(node *x){
node *y=null;
while (x!=null){
splay(x);
if (x->ch[1]!=null) x->ch[1]->Mark(-x->tree),x->ch[1]->CMark(-x->tree);
if (y!=null) y->Mark(x->tree),y->CMark(x->tree);
x->ch[1]->p=null; x->ch[1]->fat=x;
x->setc(y,1); y->fat=null;
x->update();
y=x; x=x->fat;
}
return y;
}
void Cut(node *x){
Access(x); splay(x);
x->ch[0]->p=null; x->ch[0]=null;
x->update();
}
void Link(node *x,node *y){
Access(y);
splay(y);
y->fat=x;
Access(x);
splay(x);
if (x->tree) y->CMark(-x->tree);
if (x->tree) y->Mark(-x->tree);
Access(y);
}
node *LCA(node *x,node *y){
Access(x);
return Access(y);
}
void Maintain(node *x,int v){
Access(x); splay(x);
x->w+=v; x->tree+=v;
x->update();
}
void Add(node *x,int y){
Access(x); splay(x);
x->w+=y; x->update();
}
void Change(node *x,node *y,node *z,node *lca,int v){
if (lca==x){
Access(y); if (z) Access(z);
splay(y); y->Mark(v); return;
}
if (lca==y){
Access(x); if (z) Access(z);
splay(x); x->Mark(v); return;
}
Access(x); Access(y); if (z) Access(z);
splay(y); y->Mark(v);
splay(x); x->Mark(v);
}
int QSum(node *x,node *y,node *z,node *lca){
if (lca==x){
Access(y); if (z) Access(z);
splay(y);
int tmp=0; if (y->fat!=null) splay(y->fat),tmp=y->fat->tree;
return y->Sum+tmp*y->size;
}
if (lca==y){
Access(x); if (z) Access(z);
splay(x);
int tmp=0; if (x->fat!=null) splay(x->fat),tmp=x->fat->tree;
return x->Sum+tmp*x->size;
}
Access(x); Access(y); if (z) Access(z);
splay(y);
int tmp=0; if (y->fat!=null) splay(y->fat),tmp=y->fat->tree;
splay(x); splay(x->fat);
return x->Sum+(tmp+x->fat->tree)*x->size+x->fat->Sum+tmp*x->fat->size;
}
int QMax(node *x,node *y,node *z,node *lca){
if (lca==x){
Access(y); if (z) Access(z);
splay(y);
int tmp=0; if (y->fat!=null) splay(y->fat),tmp=y->fat->tree;
return y->Max+tmp;
}
if (lca==y){
Access(x); if (z) Access(z);
splay(x);
int tmp=0; if (x->fat!=null) splay(x->fat),tmp=x->fat->tree;
return x->Max+tmp;
}
Access(x); Access(y); if (z) Access(z);
splay(y);
int tmp=0; if (y->fat!=null) splay(y->fat),tmp=y->fat->tree;
splay(x); splay(x->fat);
return max(x->Max+x->fat->tree,x->fat->Max)+tmp;
}
}LCT;
int n; int f[N];
Splay::node *pos[N];
inline void Pre(){
for (int i=1;i<=n;i++){
pos[i]=LCT.Mem+i;
pos[i]->fat=pos[i]->p=pos[i]->ch[0]=pos[i]->ch[1]=LCT.null;
pos[i]->tree=pos[i]->chadd=pos[i]->Sum=pos[i]->Max=pos[i]->w=pos[i]->add=0;
pos[i]->size=1; pos[i]->idx=i;
}
}
int main(){
int ix,iy,iz,Q; int order;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
Pre();
for (int i=2;i<=n;i++)
read(ix),LCT.Link(pos[ix],pos[i]),f[i]=ix;
read(Q);
while (Q--){
read(order);
read(ix); read(iy);
if (order==0){
LCT.Add(pos[ix],iy);
}else if (order==1){
read(iz);
Splay::node *lca=LCT.LCA(pos[ix],pos[iy]);
int flca=f[lca->idx];
LCT.Change(pos[ix],pos[iy],pos[flca],lca,iz);
}else if (order==2){
LCT.Maintain(pos[ix],iy);
}else if (order==3){
Splay::node *lca=LCT.LCA(pos[ix],pos[iy]);
int flca=f[lca->idx];
printf("%d\n",LCT.QSum(pos[ix],pos[iy],pos[flca],lca));
}else if (order==4){
Splay::node *lca=LCT.LCA(pos[ix],pos[iy]);
int flca=f[lca->idx];
printf("%d\n",LCT.QMax(pos[ix],pos[iy],pos[flca],lca));
}else if (order==5){
Splay::node *lca=LCT.LCA(pos[ix],pos[iy]);
if (lca==pos[ix]) continue;
LCT.Cut(pos[ix]);
LCT.Link(pos[iy],pos[ix]);
f[ix]=iy;
}
}
return 0;
}