BZOJ3786 星际探索

@(BZOJ)[DFS序, Splay]

Description

物理学家小C的研究正遇到某个瓶颈。
他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球。主星球没有依赖星球。
我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c.
对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的。并且从星球a出发只能直接到达它的依赖星球b.
每个星球i都有一个能量系数wi.小C想进行若干次实验,第i次实验,他将从飞船上向星球di发射一个初始能量为0的能量收集器,能量收集器会从星球di开始前往主星球,并收集沿途每个星球的部分能量,收集能量的多少等于这个星球的能量系数。
但是星系的构成并不是一成不变的,某些时刻,星系可能由于某些复杂的原因发生变化。
有些时刻,某个星球能量激发,将使得所有依赖于它的星球以及他自己的能量系数均增加一个定值。还有可能在某些时刻,某个星球的依赖星球会发生变化,但变化后依然满足依赖关系是无环的。
现在小C已经测定了时刻0时每个星球的能量系数,以及每个星球(除了主星球之外)的依赖星球。接下来的m个时刻,每个时刻都会发生一些事件。其中小C可能会进行若干次实验,对于他的每一次实验,请你告诉他这一次实验能量收集器的最终能量是多少。

Input

第一行一个整数n,表示星系的星球数。
接下来n-1行每行一个整数,分别表示星球2-n的依赖星球编号。
接下来一行n个整数,表示每个星球在时刻0时的初始能量系数wi.
接下来一行一个整数m,表示事件的总数。
事件分为以下三种类型。
(1)"Q di"表示小C要开始一次实验,收集器的初始位置在星球di.
(2)"C xi yi"表示星球xi的依赖星球变为了星球yi.
(3)"F pi qi"表示星球pi能量激发,常数为qi.

Output

对于每一个事件类型为Q的事件,输出一行一个整数,表示此次实验的收集器最终能量。

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
{
    int head[N], top;
      
    struct edge
    {
        int v, nxt;
    }edg[M];
      
    inline void init()
    {
        memset(head, -1, sizeof(head));
        top = 0;
    }
      
    inline void addEdge(int u, int v)
    {
        edg[top].v = v, edg[top].nxt = head[u];
        head[u] = top ++;
    }
      
    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.addEdge(pre, i);
    }
      
    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  阅读(244)  评论(0编辑  收藏  举报