• cdoj 574 High-level ancients dfs序+线段树


    High-level ancients

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    http://acm.uestc.edu.cn/#/problem/show/574

    Description

    Love8909 is keen on the history of Kingdom ACM. He admires the heroic undertakings of Lxhgww and Haibo. Inspired by those sagas, Love8909 picked up his courage and tried to build up his own kingdom. He named it as A230.

    After hard working for several years, Love8909 is about to fulfill his dream. However, there is still one thing to do: setting up the defense network. As Kingdom EDC looks at territory and people of A230 fiercely as a tiger does, Love8909 has to make it as soon as possible.

    The defense network Love8909 wants to use is the same as the one used by Lxhgww and Haibo. He also connects all cities with roads which form a tree structure, and the capital city is City 1, which is the root of this tree. Love8909 sends commands to inform cities to add soldiers. The command, being same to those of the ancients, with two values, X and K, means sending K soldiers to City X, sending K+1 soldiers to sons of City X, sending K+2 soldiers to sons of sons of City X and so on. Initially there are no soldiers in any city.

    title

    Love8909 may adjust the arrangement of soldiers ever and again. He asks questions about how many soldiers in the subtree rooted at City X. A subtree rooted at City X includes City X itself and all of its descendants. As Love8909's military counselor, you are responsible to complete all his commands and answer his questions.

    Input

    The first line of the input will be an integer T (T20) indicating the number of cases.

    For each case, the first line contains two integers: N P, representing the number of cities in A230 and number of operations given by love8909.

    The next line lists N1 integers, in which the ith number, denoted as Xi+1, represents there is a road from City Xi+1 to City i+1. Note that the City 1has been omitted. 1Xi+1N for 2iN.

    Then P lines follow, each gives an operation. Each operation belongs to either kind:

    • A X K. An adding-soldier command.
    • Q X. A question about how many soldiers in the subtree rooted at City X.

    We guarantee that the cities form a rooted tree and the root is at City 1, which is the capital.

    1N500001P1000001XN0K1000.

    Output

    For each case, print Case #k: first in a single line, in which k represents the case number which starts from 1. Then for each Query X operation, print the answer in a single line.

    Sample Input

    1
    7 10
    1 1 2 2 5 5
    Q 1
    A 2 1
    Q 1
    Q 2
    Q 5
    A 5 0
    Q 5
    A 3 1
    Q 1
    Q 2

    Sample Output

    Case #1:
    0
    11
    11
    8
    10
    14
    13

    HINT

    题意

    给你一棵以1为根的树,有两个操作

    1.A x k,让x增加k,x的儿子增加k+1,x的孙子增加k+2....x的t代儿子增加k+t

    2.Q x , 查询x的子树的权值和是多少

    题解:

    看到处理子树问题,很显然的dfs序

    dfs离散之后,维护线段树区间和,区间更新

    我们很容易看出,他的更新是和deep有关的,deep越深的,更新越大

    那么我们对于每个节点i,先区间更新y-deep[x],然后再使得更新一次,使得每个节点i增加deep[i]就好了

    这样每个属于x的子树的都更新了 y - deep[x] + deep[i]

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<vector>
    using namespace std;
    #define maxn 100010
    struct Node
    {
        int l,r,d,val;
    };
    Node node[maxn];
    vector<int>Q[maxn];
    int TTT[maxn];
    int cnt = 1;
    void dfs(int x,int fa,int d)
    {
        node[x].l = cnt;
        node[x].d = d;
        TTT[cnt]=x;
        cnt++;
        for(int i=0;i<Q[x].size();i++)
        {
            int v = Q[x][i];
            if(v==fa)continue;
            dfs(v,x,d+1);
        }
        node[x].r = cnt;
    }
    int d[maxn];
    struct Seg
    {
        typedef long long SgTreeDataType;
        struct treenode
        {
          int L , R  ;
          SgTreeDataType sum , lazy1 , lazy2;
        };
    
        treenode tree[maxn*4];
    
        inline void push_down(int o)
        {
            SgTreeDataType lazyval1 = tree[o].lazy1;
            SgTreeDataType lazyval2 = tree[o].lazy2;
            if(lazyval1==0&&lazyval2==0)return;
            int L = tree[o].L , R = tree[o].R;
            int mid = (L+R)/2;
            tree[2*o].lazy1+=lazyval1;tree[2*o].sum+=lazyval1*(mid-L+1);
            tree[2*o+1].lazy1+=lazyval1;tree[2*o+1].sum+=lazyval1*(R-mid);
    
            tree[2*o].lazy2+=lazyval2;tree[2*o].sum+=lazyval2*d[2*o];
            tree[2*o+1].lazy2+=lazyval2;tree[2*o+1].sum+=lazyval2*d[2*o+1];
            tree[o].lazy1 = tree[o].lazy2 = 0;
        }
    
        inline void push_up(int o)
        {
            tree[o].sum = tree[2*o].sum + tree[2*o+1].sum;
        }
    
        inline void build_tree(int L , int R , int o)
        {
            tree[o].L = L , tree[o].R = R,tree[o].sum = tree[o].lazy1 = tree[o].lazy2 = 0;
            if(L==R)
                d[o]=node[TTT[L]].d;
            if (R > L)
            {
                int mid = (L+R) >> 1;
                build_tree(L,mid,o*2);
                build_tree(mid+1,R,o*2+1);
                d[o]=d[o*2]+d[o*2+1];
            }
        }
    
        inline void updata1(int QL,int QR,SgTreeDataType v,int o)
        {
            int L = tree[o].L , R = tree[o].R;
            if (QL <= L && R <= QR)
            {
                tree[o].lazy1 += v;
                tree[o].sum += v * (R-L+1);
            }
            else
            {
                push_down(o);
                int mid = (L+R)>>1;
                if (QL <= mid) updata1(QL,QR,v,o*2);
                if (QR >  mid) updata1(QL,QR,v,o*2+1);
                push_up(o);
            }
        }
    
        inline void updata2(int QL,int QR,SgTreeDataType v,int o)
        {
            int L = tree[o].L , R = tree[o].R;
            if (QL <= L && R <= QR)
            {
                tree[o].lazy2+=v;
                tree[o].sum+=v*d[o];
            }
            else
            {
                push_down(o);
                int mid = (L+R)>>1;
                if (QL <= mid) updata2(QL,QR,v,o*2);
                if (QR >  mid) updata2(QL,QR,v,o*2+1);
                push_up(o);
            }
        }
    
        inline SgTreeDataType query(int QL,int QR,int o)
        {
            int L = tree[o].L , R = tree[o].R;
            if (QL <= L && R <= QR) return tree[o].sum;
            else
            {
                push_down(o);
                int mid = (L+R)>>1;
                SgTreeDataType res = 0;
                if (QL <= mid) res += query(QL,QR,2*o);
                if (QR > mid) res += query(QL,QR,2*o+1);
                push_up(o);
                return res;
            }
        }
    }T;
    
    
    int main()
    {
        int t;scanf("%d",&t);
        for(int cas=1;cas<=t;cas++)
        {
            printf("Case #%d:
    ",cas);
            int n,q;
            scanf("%d%d",&n,&q);
            for(int i=0;i<=n;i++)Q[i].clear(),node[i].val=0;
            cnt = 1;
            for(int i=2;i<=n;i++)
            {
                int x,y;scanf("%d",&x);
                y=i;
                Q[x].push_back(y);
                Q[y].push_back(x);
            }
            dfs(1,-1,1);
            T.build_tree(1,n,1);
            string ch;
            while(q--)
            {
                cin>>ch;
                if(ch[0]=='Q')
                {
                    int x;scanf("%d",&x);
                    printf("%lld
    ",T.query(node[x].l,node[x].r-1,1));
                }
                else
                {
                    int x,y;scanf("%d%d",&x,&y);
                    T.updata1(node[x].l,node[x].r-1,y-node[x].d,1);
                    T.updata2(node[x].l,node[x].r-1,1,1);
                }
            }
        }
    }
  • 相关阅读:
    缓存雪崩与缓存穿透
    读取表中最大值
    使用vscode在谷歌上运行代码
    elment 中tree组件展开所有和收缩所有节点
    深度系统商店提示无法安装软件依赖错误
    诗词,理解,品论
    《45个十分钟读懂资本论》原文、适合朗读版和个人见解
    《论持久战》全文
    OSError: [WinError 126] 找不到指定的模块。
    C++ 获取序列最大(或最小)的 N 个元素
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4996401.html
Copyright © 2020-2023  润新知