zoukankan      html  css  js  c++  java
  • 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
    ", 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;
            }
        }
    }
    
    
  • 相关阅读:
    【转】dip,px,pt,sp 的区别
    JAVA中报错 : org.springframework.beans.factory.BeanCreationException
    ExecuteNonQuery及对比
    ParameterDirection参数类型
    WinForm控件组合使用
    DataGridView控件内实现修改与删除
    DataView筛选绑定
    动态反射
    反射属性名和属性值
    接口与抽象类
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6687353.html
Copyright © 2011-2022 走看看