# BZOJ 3786 星系探索 DFS序+Splay

667 篇文章 1 订阅
11 篇文章 0 订阅
6 篇文章 0 订阅

1.询问某个点到根路径上的点权和

2.修改某个点的父亲，保证修改之后仍然是一棵树

3.将某个点所在子树的所有点权加上一个值

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
typedef long long ll;
struct abcd{
abcd *ls,*rs,*fa;
ll num,sum;
int sta,pos,neg;
abcd (ll x,int _sta);
void Push_Up();
void Push_Down();
}*null=new abcd(0,0),*root,*tree[M][2];
struct edge{
int to,next;
}table[M];
int n,m;
int a[M];
abcd :: abcd(ll x,int _sta)
{
ls=rs=fa=null;
num=sum=x*(_sta==1?1:-1);
sta=_sta;
pos=neg=0;
if(sta==1) pos++;
if(sta==2) neg++;
}
void abcd :: Push_Up()
{
sum=ls->sum+rs->sum+num;
pos=ls->pos+rs->pos+(sta==1);
neg=ls->neg+rs->neg+(sta==2);
}
void abcd :: Push_Down()
{
{
}
}
{
if(this==null)
return ;
num+=x*(sta==1?1:-1);
sum+=x*(pos-neg);
}
void Push_Down(abcd *x)
{
static abcd *stack[M<<1];
static int top=0;
for(;x!=null;x=x->fa)
stack[++top]=x;
while(top)
stack[top--]->Push_Down();

}
void Zig(abcd *x)
{
abcd *y=x->fa;
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
x->fa=y->fa;
if(y->fa->ls==y)
y->fa->ls=x;
else
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(root==y)
root=x;
}
void Zag(abcd *x)
{
abcd *y=x->fa;
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
x->fa=y->fa;
if(y->fa->ls==y)
y->fa->ls=x;
else
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(root==y)
root=x;
}
void Splay(abcd *x,abcd *tar)
{
Push_Down(x);
while(1)
{
abcd *y=x->fa,*z=y->fa;
if(y==tar) break;
if(z==tar)
{
if(x==y->ls) Zig(x);
else Zag(x);
break;
}
if(x==y->ls)
{
if(y==z->ls)
Zig(y);
Zig(x);
}
else
{
if(y==z->rs)
Zag(y);
Zag(x);
}
}
x->Push_Up();
}
abcd* Insert(ll x,int _sta)
{
abcd *y=root;
while(y->rs!=null)
y=y->rs;
y->rs=new abcd(x,_sta);
y->rs->fa=y;
y->Push_Up();
Splay(y->rs,null);
return root;
}
abcd* Find_Min(abcd *x)
{
while(x->ls!=null)
x=x->ls;
return x;
}
abcd* Find_Max(abcd *x)
{
while(x->rs!=null)
x=x->rs;
return x;
}
void Move_To_Root(abcd *x,abcd *y)
{
Splay(x,null);
abcd *temp1=Find_Max(root->ls);
Splay(y,null);
abcd *temp2=Find_Min(root->rs);
Splay(temp1,null);
Splay(temp2,root);
}
{
table[++tot].to=y;
}
void DFS(int x)
{
int i;
tree[x][0]=Insert(a[x],1);
DFS(table[i].to);
tree[x][1]=Insert(a[x],2);
}
int main()
{
int i,x,y;
char p[10];
cin>>n;
for(i=2;i<=n;i++)
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
root=new abcd(19980402,3);
DFS(1);
Insert(19980402,4);
cin>>m;
for(i=1;i<=m;i++)
{
scanf("%s",p);
switch(p[0])
{
case 'Q':
scanf("%d",&x);
Move_To_Root(tree[1][0],tree[x][0]);
printf("%lld\n",root->rs->ls->sum);
break;
case 'C':
{
scanf("%d%d",&x,&y);
Move_To_Root(tree[x][0],tree[x][1]);
abcd *temp=root->rs->ls;
root->rs->ls=null;
root->rs->Push_Up();
root->Push_Up();
Splay(tree[y][0],null);
Splay(Find_Min(root->rs),root);
root->rs->ls=temp;
temp->fa=root->rs;
root->rs->Push_Up();
root->Push_Up();
break;
}
case 'F':
scanf("%d%d",&x,&y);
Move_To_Root(tree[x][0],tree[x][1]);
break;
}
}
}

• 4
点赞
• 1
收藏
觉得还不错? 一键收藏
• 0
评论
02-08 421
02-05
12-03 110
12-06 951
06-14 410
11-03
08-19
08-21
10-13
12-27 463
09-29 173
12-27 585
09-09 47
01-15 75
09-25 478

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。