# bzoj3786 星系探索

1.区间求和（splay基础）

2.区间加法（还是splay基础）

3.区间移动（其实就是删除+插入）

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 100050
#define ll long long
ll n,m,hed[N],cnt;
struct EDGE
{
ll to,nxt;
}e[N];
void ae(ll f,ll t)
{
e[++cnt].to = t;
e[cnt].nxt = hed[f];
hed[f] = cnt;
}
struct Splay
{
ll ch[2],fa,vl,siz,sum,mrk;
ll kk,sk;
}tr[2*N];
ll tin[N],tout[N],tot=1,a[N],rt;
void dfs(ll u)
{
tin[u]=++tot;
tr[tot].vl = a[u];
tr[tot].kk = 1;
tr[tot].sk = 1;
for(ll j=hed[u];j;j=e[j].nxt)dfs(e[j].to);
tout[u]=++tot;
tr[tot].vl = -a[u];
tr[tot].kk = -1;
tr[tot].sk = -1;
}
void update(ll u)
{
ll l = tr[u].ch[0],r = tr[u].ch[1];
tr[u].siz = tr[l].siz+tr[r].siz+1;
tr[u].sk = tr[l].sk+tr[r].sk+tr[u].kk;
tr[u].sum = tr[l].sum+tr[r].sum+tr[u].vl;
}
void pushdown(ll x)
{
ll l = tr[x].ch[0],r = tr[x].ch[1],k = tr[x].mrk;
if(k)
{
if(l)tr[l].vl+=k*tr[l].kk,tr[l].sum+=tr[l].sk*k,tr[l].mrk+=k;
if(r)tr[r].vl+=k*tr[r].kk,tr[r].sum+=tr[r].sk*k,tr[r].mrk+=k;
tr[x].mrk=0;
}
}
void build(ll l,ll r,ll f)
{
if(l>r)return ;
ll mid = (l+r)>>1;
if(l!=r)build(l,mid-1,mid),build(mid+1,r,mid);
tr[mid].fa = f;
tr[f].ch[mid>=f] = mid;
update(mid);
}
void rotate(ll x)
{
ll y = tr[x].fa,z = tr[y].fa,k = (tr[y].ch[1]==x);
tr[y].ch[k] = tr[x].ch[k^1],tr[tr[x].ch[k^1]].fa = y;
tr[x].ch[k^1] = y,tr[y].fa = x;
tr[z].ch[tr[z].ch[1]==y]=x,tr[x].fa = z;
update(y),update(x);
}
void splay(ll x,ll goal)
{
while(tr[x].fa!=goal)
{
ll y = tr[x].fa,z = tr[y].fa;
if(z!=goal)
((tr[y].ch[1]==x)^(tr[z].ch[1]==y))?rotate(x):rotate(y);
rotate(x);
}
if(!goal)rt = x;
}
ll get_th(ll x)
{
ll ret = 0;
if(x==rt)ret = tr[tr[x].ch[0]].siz+1;
else if(x==tr[tr[x].fa].ch[0])ret = get_th(tr[x].fa)-1-tr[tr[x].ch[1]].siz;
else ret = get_th(tr[x].fa)+1+tr[tr[x].ch[0]].siz;
pushdown(x);
return ret;
}
ll find_kth(ll x,ll k)
{
pushdown(x);
ll t = tr[tr[x].ch[0]].siz;
if(k<=t)return find_kth(tr[x].ch[0],k);
else if(k==t+1)return x;
else return find_kth(tr[x].ch[1],k-1-t);
}
void ccc(ll x,ll y)
{
ll l,r;
l = get_th(tin[x])-1,r = get_th(tout[x])+1;
l = find_kth(rt,l),r = find_kth(rt,r);
splay(l,0),splay(r,l);
ll z = tr[tr[rt].ch[1]].ch[0];
tr[tr[z].fa].ch[0]=0;
update(tr[z].fa),update(rt);
l = get_th(tin[y]),r = l+1;
l = find_kth(rt,l),r = find_kth(rt,r);
splay(l,0),splay(r,l);
tr[z].fa = tr[rt].ch[1];
tr[tr[rt].ch[1]].ch[0] = z;
update(tr[z].fa),update(rt);
}
void fff(ll x,ll d)
{
ll l,r;
l = get_th(tin[x])-1;
r = get_th(tout[x])+1;
l = find_kth(rt,l),r = find_kth(rt,r);
splay(l,0),splay(r,l);
ll z = tr[r].ch[0];
tr[z].mrk+=d;
tr[z].vl+=d*tr[z].kk;
tr[z].sum+=d*tr[z].sk;
}
int main()
{
scanf("%lld",&n);
for(ll f,i=2;i<=n;i++)
{
scanf("%lld",&f);
ae(f,i);
}
for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);
dfs(1);
build(1,2*n+2,0);
rt = (2*n+3)>>1;
scanf("%lld",&m);
char ch[2];
ll x,y;
for(ll i=1;i<=m;i++)
{
scanf("%s",ch);
if(ch[0]=='Q')
{
scanf("%lld",&x);
get_th(tin[x]);
splay(tin[x],0);
printf("%lld\n",tr[tr[rt].ch[0]].sum+tr[rt].vl);
}else if(ch[0]=='C')
{
scanf("%lld%lld",&x,&y);
ccc(x,y);
}else
{
scanf("%lld%lld",&x,&y);
fff(x,y);
}
}
return 0;
}


posted @ 2018-09-09 23:22  LiGuanlin  阅读(119)  评论(0编辑  收藏  举报