zoukankan      html  css  js  c++  java
  • Codeforces Round #169 (Div. 2) E. Little Girl and Problem on Trees dfs序+线段树

    E. Little Girl and Problem on Trees
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    A little girl loves problems on trees very much. Here's one of them.

    A tree is an undirected connected graph, not containing cycles. The degree of node x in the tree is the number of nodes y of the tree, such that each of them is connected with node x by some edge of the tree.

    Let's consider a tree that consists of n nodes. We'll consider the tree's nodes indexed from 1 to n. The cosidered tree has the following property: each node except for node number 1 has the degree of at most 2.

    Initially, each node of the tree contains number 0. Your task is to quickly process the requests of two types:

    • Request of form: v x d. In reply to the request you should add x to all numbers that are written in the nodes that are located at the distance of at most d from node v. The distance between two nodes is the number of edges on the shortest path between them.
    • Request of form: v. In reply to the request you should print the current number that is written in node v.
    Input

    The first line contains integers n (2 ≤ n ≤ 105) and q (1 ≤ q ≤ 105) — the number of tree nodes and the number of requests, correspondingly.

    Each of the next n  -  1 lines contains two integers ui and vi (1 ≤ ui, vi ≤ nui ≠ vi), that show that there is an edge between nodes uiand vi. Each edge's description occurs in the input exactly once. It is guaranteed that the given graph is a tree that has the property that is described in the statement.

    Next q lines describe the requests.

    • The request to add has the following format: v x d (1 ≤ v ≤ n1 ≤ x ≤ 104, 1 ≤ d < n).
    • The request to print the node value has the following format: v (1 ≤ v ≤ n).

    The numbers in the lines are separated by single spaces.

    Output

    For each request to print the node value print an integer — the reply to the request.

    Examples
    input
    3 6
    1 2
    1 3
    0 3 1 2
    0 2 3 1
    0 1 5 2
    1 1
    1 2
    1 3
    output
    9
    9
    6
    input
    6 11
    1 2
    2 5
    5 4
    1 6
    1 3
    0 3 1 3
    0 3 4 5
    0 2 1 4
    0 1 5 5
    0 4 6 2
    1 1
    1 2
    1 3
    1 4
    1 5
    1 6
    output
    11
    17
    11
    16
    17
    11

     题意:给你一棵树,除了点1以为的点最多的度数为2,0表示以某个点v为半径d内的点权值+x

       1表示查询v的权值大小;

    思路:这题有一个关键点,就是除了1以为的度数最大为2,则表示如果以1为根的话,每条都是直链,没有开叉;

       对于直链的话,可以进行dfs序标号,更新一条链的话就可以区间更新;

       对于半径范围内的话,表示到根的距离减去d,以1为中心半径进行求解;

       不能一条一条的去暴力链,开两个线段树,一个暴力一条链,一个存半径;

        =_=,详见代码;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-14
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e5+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
    struct is
    {
        int v,next;
    } edge[N<<1];
    int head[N],edg,dep[N];
    int in[N],out[N],tot;
    void init()
    {
        memset(head,-1,sizeof(head));
        edg=0;
        tot=0;
    }
    void add(int u,int v)
    {
        edg++;
        edge[edg].v=v;
        edge[edg].next=head[u];
        head[u]=edg;
    }
    void dfs(int u,int fa,int deep)
    {
        dep[u]=deep;
        tot++;
        in[u]=tot;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v;
            if(v==fa)continue;
            dfs(v,u,deep+1);
        }
        out[u]=tot;
    }
    struct linetree
    {
        int maxx[N<<2],lazy[N<<2];
        void pushup(int pos)
        {
            maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]);
        }
        void pushdown(int pos)
        {
            if(lazy[pos])
            {
                int x=lazy[pos];
                lazy[pos<<1]+=x;
                lazy[pos<<1|1]+=x;
                maxx[pos<<1|1]+=x;
                maxx[pos<<1]+=x;
                lazy[pos]=0;
            }
        }
        void build(int l,int r,int pos)
        {
            if(l==r)
            {
                maxx[pos]=0;
                lazy[pos]=0;
                return;
            }
            int mid=(l+r)>>1;
            build(l,mid,pos<<1);
            build(mid+1,r,pos<<1|1);
            pushup(pos);
        }
        void update(int L,int R,int c,int l,int r,int pos)
        {
            if(L<=l&&r<=R)
            {
                maxx[pos]+=c;
                lazy[pos]+=c;
                return;
            }
            pushdown(pos);
            int mid=(l+r)>>1;
            if(L<=mid)
                update(L,R,c,l,mid,pos<<1);
            if(R>mid)
                update(L,R,c,mid+1,r,pos<<1|1);
            pushup(pos);
        }
        int query(int p,int l,int r,int pos)
        {
            if(l==r)return maxx[pos];
            pushdown(pos);
            int mid=(l+r)>>1;
            if(p<=mid)
                return query(p,l,mid,pos<<1);
            else return query(p,mid+1,r,pos<<1|1);
        }
    };
    linetree tree,tree2;
    int main()
    {
        init();
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i=1; i<n; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,-1,0);
        tree.build(1,n,1);
        tree2.build(1,n,1);
        while(q--)
        {
            int flag;
            scanf("%d",&flag);
            if(flag)
            {
                int x;
                scanf("%d",&x);
                if(x!=1)
                printf("%d
    ",tree.query(in[x],1,n,1)+tree2.query(dep[x],1,n,1));
                else
                    printf("%d
    ",tree.query(in[1],1,n,1));
            }
            else
            {
                int v,x,d;
                scanf("%d%d%d",&v,&x,&d);
                if(v==1)
                {
                    tree.update(1,1,x,1,n,1);
                    tree2.update(1,d,x,1,n,1);
                }
                else if(dep[v]<d)
                {
                    int L=d-dep[v];
                    int l=in[v]-dep[v]+L+1;
                    int r=min(in[v]+d,out[v]);
                    tree2.update(1,L,x,1,n,1);
                    tree.update(1,1,x,1,n,1);
                    if(l<=r)tree.update(l,r,x,1,n,1);
                }
                else if(dep[v]==d)
                {
                    int L=in[v]-d+1,R=min(out[v],in[v]+d);
                    tree.update(L,R,x,1,n,1);
                    tree.update(1,1,x,1,n,1);
                }
                else
                {
                    int L=in[v]-d,R=min(out[v],in[v]+d);
                    tree.update(L,R,x,1,n,1);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    stl-序列式容器
    BFS
    Hash
    二分法
    草稿1
    红黑树的左旋、右旋和颜色变换
    动态规划
    自动驾驶-安全
    二叉树

  • 原文地址:https://www.cnblogs.com/jhz033/p/6424001.html
Copyright © 2011-2022 走看看