# BZOJ3786 星际探索

@(BZOJ)[DFS序, Splay]

## Input

(1)"Q di"表示小C要开始一次实验,收集器的初始位置在星球di.
(2)"C xi yi"表示星球xi的依赖星球变为了星球yi.
(3)"F pi qi"表示星球pi能量激发，常数为qi.

## Sample Input

3
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2


## Sample Output

9
15
25


## HINT

$$n≤100000,m≤300000,1<di,xi≤n,wi,qi≤100000$$. 保证操作合法.

## Solution

splay tree维护DFN序.

#include <cstdio>
#include <cctype>
#include <cstring>

const int N = 1 << 17, M = 1 << 19;
int L[N], R[N];

namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1;
char c;

while(! isdigit(c = getchar()))
if(c == '-')
sgn *= -1;

while(isdigit(c))
a = a * 10 + c - '0', c = getchar();

return a * sgn;
}

inline char getChar()
{
char c;

while(! isgraph(c = getchar()));

return c;
}
}

struct tree
{

struct edge
{
int v, nxt;
}edg[M];

inline void init()
{
top = 0;
}

inline void addEdge(int u, int v)
{
edg[top].v = v, edg[top].nxt = head[u];
}

int clk;

void DFS(int u)
{
L[u] = clk ++;

for(int i = head[u]; ~ i; i = edg[i].nxt)
DFS(edg[i].v);

R[u] = clk ++;
}
}org;

struct splayTree
{
struct node
{
int suc[2], pre;
long long w, sgn, sum, tag, sz;

inline node()
{
sz = w = sgn = sum = tag = 0;
pre = suc[0] = suc[1] = -1;
}
}nd[N << 1];

inline void update(int u)
{
nd[u].sum = nd[u].w * nd[u].sgn;
nd[u].sz = nd[u].sgn;

if(~ nd[u].suc[0])
nd[u].sum += nd[nd[u].suc[0]].sum, nd[u].sz += nd[nd[u].suc[0]].sz;

if(~ nd[u].suc[1])
nd[u].sum += nd[nd[u].suc[1]].sum, nd[u].sz += nd[nd[u].suc[1]].sz;
}

int root;

int build(int L, int R, int pre)
{
if(L > R)
return -1;

int mid = L + R >> 1;
nd[mid].pre = pre;
nd[mid].suc[0] = build(L, mid - 1, mid);
nd[mid].suc[1] = build(mid + 1, R, mid);
update(mid);
return mid;
}

inline void pushdown(int u)
{
if(nd[u].pre != -1)
pushdown(nd[u].pre);

if(~ nd[u].suc[0])
nd[nd[u].suc[0]].tag += nd[u].tag, nd[nd[u].suc[0]].w += nd[u].tag, nd[nd[u].suc[0]].sum += nd[u].tag * nd[nd[u].suc[0]].sz;

if(~ nd[u].suc[1])
nd[nd[u].suc[1]].tag += nd[u].tag, nd[nd[u].suc[1]].w += nd[u].tag, nd[nd[u].suc[1]].sum += nd[u].tag * nd[nd[u].suc[1]].sz;

nd[u].tag = 0;
}

inline int getRelation(int u)
{
if(nd[u].pre == -1)
return -1;

return u == nd[nd[u].pre].suc[1];
}

inline void rotate(int u)
{
int pre = nd[u].pre, prepre = nd[pre].pre, k = getRelation(u);

if(~ nd[u].suc[k ^ 1])
nd[nd[u].suc[k ^ 1]].pre = pre;

nd[pre].suc[k] = nd[u].suc[k ^ 1];
nd[u].suc[k ^ 1] = pre;
nd[u].pre = prepre;

if(~ prepre)
nd[prepre].suc[getRelation(pre)] = u;

nd[pre].pre = u;
update(pre), update(u);
}

inline void splay(int u, int bnd)
{
pushdown(u);

while(nd[u].pre != bnd)
{
int pre = nd[u].pre;

if(nd[pre].pre != bnd)
rotate(getRelation(u) == getRelation(pre) ? pre : u);

rotate(u);
}
}

inline int getLast(int u)
{
splay(u, -1);
u = nd[u].suc[0];

while(~ nd[u].suc[1])
u = nd[u].suc[1];

return u;
}

inline int getNext(int u)
{
splay(u, -1);
u = nd[u].suc[1];

while(~ nd[u].suc[0])
u = nd[u].suc[0];

return u;
}
}seq;

int main()
{
#ifndef ONLINE_JUDGE
freopen("BZOJ3786.in", "r", stdin);
freopen("BZOJ3786.out", "w", stdout);
#endif

using namespace Zeonfai;
int n = getInt();
org.init();

for(int i = 2; i <= n; ++ i)
{
int pre = getInt();
}

org.clk = 1;
org.DFS(1);

for(int i = 1; i <= n; ++ i)
{
int w = getInt();
seq.nd[L[i]].w = seq.nd[R[i]].w = w;
seq.nd[L[i]].sgn = 1, seq.nd[R[i]].sgn = -1;
}

seq.root = seq.build(0, org.clk, -1);
int m = getInt();

for(int i = 0; i < m; ++ i)
{
char opt = getChar();

if(opt == 'Q')
{
int u = getInt();
seq.splay(L[u], -1);
printf("%lld\n", seq.nd[seq.nd[L[u]].suc[0]].sum + seq.nd[L[u]].w);
}
else if(opt == 'C')
{
int u = getInt(), v = getInt();
int lst = seq.getLast(L[u]), nxt = seq.getNext(R[u]);
seq.splay(lst, -1);
seq.splay(nxt, lst);
int tmp = seq.nd[nxt].suc[0];
seq.nd[nxt].suc[0] = -1;
seq.update(nxt);
lst = L[v];
nxt = seq.getNext(L[v]);
seq.splay(lst, -1);
seq.splay(nxt, lst);
seq.nd[tmp].pre = nxt;
seq.nd[nxt].suc[0] = tmp;
seq.update(nxt);
}
else if(opt == 'F')
{
int u = getInt(), inc = getInt();
int lst = seq.getLast(L[u]), nxt = seq.getNext(R[u]);
seq.splay(lst, -1);
seq.splay(nxt, lst);
seq.nd[seq.nd[nxt].suc[0]].tag += inc;
seq.nd[seq.nd[nxt].suc[0]].sum += seq.nd[seq.nd[nxt].suc[0]].sz * inc;
seq.nd[seq.nd[nxt].suc[0]].w += inc;
}
}
}


posted @ 2017-04-10 08:08  Zeonfai  阅读(278)  评论(0编辑  收藏  举报