zoukankan      html  css  js  c++  java
  • Codechef Dynamic Trees and Queries

    Home » Practice(Hard) » Dynamic Trees and Queries

    Problem Code: ANUDTQSolvedSubmit

    All submissions for this problem are available.

    Read problems statements in Mandarin Chinese and Russian.

    Given a directed tree with N nodes. You need to process M queries.
    Each node has a key and a value, a node is referenced by its key. N nodes havekeys from 0 to N-1.
    Root always has the key equal to 0. Queries can be of the following 4 types:

    1. Given a key of a node present in the tree, append a child node to it. The new node gets the smallest never-used positive integer as its key. The value of the new node will be given in the input.

    2. Given a key of a node(call it A) present in the tree. Add value to the value of all the nodes present in the subtree rooted at A.

    3. Given a key of a node(call it A) present in the tree. Remove the subtree rooted at Afrom the tree.

    4. Given a key of a node(call it A) present in the tree. Output the sum of values of all the nodes in subtree rooted at A.

    Input is encoded:

    Keys in M Queries of the input are encoded in the following way:

    Let SPECIAL = 0 initially. Whenever a query of the type 4 occurs, SPECIAL is updated to the result of that query.
    All the keys given in queries are encoded, in order to decode them you need to add SPECIAL to it.

    That is, you are given encoded_key as input, to get key use the formula key =SPECIAL + encoded_key.

    Input

    First line of input has N, the number of nodes.

    Second line has N integers, the values of given N nodes respectively.

    Then, N-1 lines follow, each has two integers u, v. which specifies an edge from u to v.

    Next line contains a single integer M, the number of queries.

    Each query consists of 2 lines, First line has the the type of query, second line is as follows:

    For queries 1 and 2, there are two integers, first one represents the key of a node in tree, second one represents the value.

    For queries 3 and 4, there is a single integer, which represents the key of a node in tree.

    Output

    For each query of type 4, output the required answer.

    Constraints

    • 1 ≤ N ≤ 10^5
    • 1 ≤ M ≤ 10^5
    • 0 ≤ u < N
    • 0 ≤ v < N, u is not equal to v
    • All the keys in the input are valid
    • If the type of the query is 3, the the key is nonzero.
    • All the rest numbers in the input are in the range [-1000, 1000]

    Example

    Input:
    2
    10 20
    0 1
    4
    4
    0
    1
    -30 5
    2
    -30 1
    4
    -30
    
    Output: 30 38

    Explanation

    Query #1

    type = 4 encoded_key = 0

    Initially SPECIAL = 0

    key = encoded_key + SPECIAL = 0

    value at 0 + value at 1 = 10 + 20 = 30 is the answer

    Now SPECIAL is updated to 30

    Query #2

    type = 1 encoded_key = -30 value = 5 

    SPECIAL = 30 

    key = encoded_key + SPECIAL = -30 + 30 = 0

    So we add a child node(with the key = 2) to the node with the key 0, the child node gets the value of 5


    EDITS MADE:

    Firstly, sorry for the mistake.

    Old : Let SPECIAL = 0 initially. Whenever a query of the type 4 occurs, SPECIAL is increased by the result of that query.

    New : Let SPECIAL = 0 initially. Whenever a query of the type 4 occurs, SPECIAL is updated to the result of that query.

    题意:给出一颗由有向边构成的树,每个节点有编号、权值

    操作1:给编号为A的点新增一个权值为val的叶子节点

    操作2:给以编号A为根的子树权值全体+val

    操作3:删除以编号为A为根的子树

    操作4:询问以编号A为根的子树的权值和

    碰到子树常用dfs序解决,但这题是动态增删,dfs序难以完成

    所以 用splay维护括号序列 来解决子树问题

    具体来说就是每加一个点,实际往splay中加一对括号

    查找子树时,找到根节点的左右括号,就确定了子树范围

    #include<cstdio>
    #define lc ch[x][0]
    #define rc ch[x][1]
    #define N 401001
    using namespace std;
    int fa[N],ch[N][2],l[N],r[N],siz[N],a[N];
    int front[N],to[N],next[N],tot,cnt;
    long long sum[N],tag[N],key[N],special;
    int n,m;
    int read()
    {
        int x=0;int f=1; char c=getchar();
        while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
        while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
        return x*f;
    } 
    long long read2()
    {
        long long x=0;int f=1; char c=getchar();
        while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
        while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
        return x*f;
    } 
    struct SPLAY
    {
        void up(int x)
        {
            siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
            sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
        }
        void accumu(int x,long long val)
        {
            key[x]+=val; 
            sum[x]+=val*siz[x];
            tag[x]+=val;
        }
        void down(int x)
        {
            if(lc) accumu(lc,tag[x]);
            if(rc) accumu(rc,tag[x]);
            tag[x]=0;
        }
        bool getson(int x)
        {
            return ch[fa[x]][1]==x;
        }
        void rotate(int x)
        {
            int y=fa[x],z=fa[y],k=ch[y][1]==x;
            if(z)  ch[z][ch[z][1]==y]=x;
            fa[x]=z;
            ch[y][k]=ch[x][k^1]; ch[x][k^1]=y;
            fa[y]=x; if(ch[y][k]) fa[ch[y][k]]=y;
            up(y);
        }
        void splay(int x,int g=0)
        {
            while(fa[x]!=g)
            {
                int y=fa[x],z=fa[y];
                if(tag[z]) down(z); 
                 if(tag[y]) down(y);
                  if(tag[x]) down(x); 
                if(z!=g) rotate(getson(x)==getson(y) ? y : x);
                rotate(x);
                up(x);
            }
        }
        int find_pre(int y)
        {
            splay(y);
            int x=ch[y][0];
            while(rc) x=rc;
            return x;
        }
        int find_suf(int y)
        {
            splay(y);
            int x=ch[y][1];
            while(lc) x=lc;
            return x;
        }
        void insert(int x,int f,int val)
        {
            int pre=l[f],suf=find_suf(l[f]);
            splay(pre); splay(suf,pre);
            l[x]=++tot; r[x]=++tot;
            ch[suf][0]=l[x]; fa[l[x]]=suf;
            ch[l[x]][1]=r[x]; fa[r[x]]=l[x];
            siz[l[x]]=siz[r[x]]=1;
            sum[l[x]]=key[l[x]]=val;
            sum[r[x]]=key[r[x]]=val;
            up(l[x]); up(suf); up(pre);    
        }
        void add(int x,int val)
        {
            int pre=find_pre(l[x]);
            int suf=find_suf(r[x]);
            splay(pre); splay(suf,pre);
            accumu(ch[suf][0],val);
            up(suf); up(pre); 
        }
        void del(int x)
        {
            int pre=find_pre(l[x]);
            int suf=find_suf(r[x]);
            splay(pre); splay(suf,pre);
            ch[suf][0]=0;
            up(suf); up(pre);
        }
        void query(int x)
        {
            int pre=find_pre(l[x]);
            int suf=find_suf(r[x]);
            splay(pre); 
            splay(suf,pre);
            special=sum[ch[suf][0]]/2;
            printf("%lld
    ",special);
        }
    }Splay;
    struct TREE
    {
        void add(int u,int v)
        {
            to[++cnt]=v; next[cnt]=front[u]; front[u]=cnt;
        }
        void dfs(int u,int f)
        {
            Splay.insert(u,f,a[u]);
            for(int i=front[u];i;i=next[i])
             dfs(to[i],u);
        }
    }Tree;
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        int u,v;
        for(int i=1;i<n;i++)
        {
            u=read(); v=read(); 
            Tree.add(++u,++v);
        }
        l[0]=++tot; r[0]=++tot; 
        siz[1]=2; siz[2]=1;
        fa[2]=1; ch[1][1]=2;
        Tree.dfs(1,0);
        m=read();
        int op; long long x;
        while(m--)
        {
            op=read(); x=read2(); x+=special; x++;
            if(op==1) { u=read();  Splay.insert(++n,x,u); }
            else if(op==2)    { u=read(); Splay.add(x,u); }
            else if(op==3) Splay.del(x);
            else Splay.query(x);
        }
    } 
  • 相关阅读:
    几个可以用到的正则表达式
    apache fileupload 文件上传,及文件进度设置获取
    Log4j日志根据配置输出到多个自定义文件
    spring3.2.2 remoting HTTP invoker 实现方式
    希望自己坚持住!
    tomcat线程一直处于RUNNABLE,不接受请求
    OM—>AR相关会计科目
    css画图
    Jquery 实现原理之 Ajax
    HTML、XHTML和HTML5区别与联系
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6860234.html
Copyright © 2011-2022 走看看