Codeforces276E:Little Girl and Problem on Trees,catsontrees

來源:互聯網
上載者:User

Codeforces276E:Little Girl and Problem on Trees,catsontrees

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: 0 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: 1 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 ui andvi. 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: 0 v x d (1 ≤ v ≤ n, 1 ≤ x ≤ 104, 1 ≤ d < n).
  • The request to print the node value has the following format: 1 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.

Sample test(s)input
3 61 21 30 3 1 20 2 3 10 1 5 21 11 21 3
output
996
input
6 111 22 55 41 61 30 3 1 30 3 4 50 2 1 40 1 5 50 4 6 21 11 21 31 41 51 6
output
111711161711

題意:一棵樹只有一個頂點,然後由這個頂點引申出多條鏈,對於輸入 0 v x d,代表把距離V節點距離在d以內的所有節點增加x,對於輸入 1 v,代表查詢v節點的值

思路:這道題參考別人的代碼的時候,發現用到了樹狀數組,但是以前並沒有做過樹狀數組,雖說能用樹狀數組做的題都能用線段樹做,但是樹狀數組還是挺巧妙的,於是臨時去看了一下樹狀數組的原理,最後結合別人的思想把這道題A了
首先我們對於一條鏈而言,當這個節點在鏈中,往下更新d的距離很好辦,但是往上更新到1節點的時候,我們假設還有d的距離沒有更新,如果我們一條條的去更新很容易逾時,於是我們可以對於整棵樹直接更新,即所有距離1為d的節點更新的狀態都是一樣的
使用new動態分配記憶體放置超記憶體

#include <iostream>#include <stdio.h>#include <string.h>#include <stack>#include <queue>#include <map>#include <set>#include <vector>#include <math.h>#include <algorithm>using namespace std;#define ls 2*i#define rs 2*i+1#define up(i,x,y) for(i=x;i<=y;i++)#define down(i,x,y) for(i=x;i>=y;i--)#define mem(a,x) memset(a,x,sizeof(a))#define w(a) while(a)#define LL long longconst double pi = acos(-1.0);#define N 100005#define mod 19999997const int INF = 0x3f3f3f3f;#define exp 1e-8//v點所在鏈的編號,所在層數,v在鏈上標號,各條鏈長度。int mark[N],level[N],pos[N],length[N],id,deep;vector<int> vec[N];struct node{    int *sum,n;    void init(int len)    {        n = len;        sum = new int[n+1];        memset(sum,0,(n+1)*sizeof(int));    }    int query(int i)    {        int ans = 0;        for(; i<=n; i+=i&-i)            ans+=sum[i];        return ans;    }    void add(int i,int x)    {        for(; i>0; i-=i&-i)            sum[i]+=x;    }    void updata(int l,int r,int x)//更新l~r區間    {        add(r,x);        add(l-1,-x);//多餘的更新減去    }} tree,*chain;int dfs(int step,int u,int pre){    int i,n = vec[u].size(),v;    level[u] = step+1;//層數要加上1所在的那層    mark[u] = id;    pos[u] = step;//在鏈上的標號不算1節點,所以不加1    up(i,0,n-1)    {        v = vec[u][i];        if(v == pre) continue;        return dfs(step+1,v,u);    }    return step;}void init(){    int i,n=vec[1].size(),len,v;    chain = new node[n];    level[1]=1;    up(i,0,n-1)//對每條鏈進行初始化    {        id = i;        v = vec[1][i];        len = dfs(1,v,1);        length[i]=len;        deep = max(len,deep);//找出最長的鏈的深度        chain[i].init(len);//更新每條鏈的深度    }    tree.init(++deep);//整棵樹的深度}int query(int v){    int ans = 0;    ans = tree.query(level[v]);    if(v!=1)    {        ans+=chain[mark[v]].query(pos[v]);    }    return ans;}void updata(int v,int x,int d){    int l,r;    if(v == 1)    {        if(deep>=1+d) r = 1+d;//比較樹深度與d的深度來確定更新深度        else r = deep;        tree.updata(1,r,x);        return;    }    //對於每條鏈,r代表往下更新的深度,l代表往上更新的深度,先更新到1節點為止    if(length[mark[v]]>=pos[v]+d) r = pos[v]+d;    else r = length[mark[v]];    if(1<=pos[v]-d) l = pos[v]-d;    else l = 1;    chain[mark[v]].updata(l,r,x);    d-=level[v]-1;    if(d>=0)//到了1節點還有剩下    {        if(deep>=1+d) r = 1+d;//以1節點為原點,更新所有鏈,深度為r        else r = deep;        tree.updata(1,r,x);        if(r>=2)//對於要求的點,由於更新了兩次,要減去這次的更新        {            if(length[mark[v]]>=r-1) r = r-1;            else r = length[mark[v]];            chain[mark[v]].updata(1,r,-x);        }    }}int main(){    int i,n,q,x,y;    scanf("%d%d",&n,&q);    up(i,1,n-1)    {        scanf("%d%d",&x,&y);        vec[x].push_back(y);        vec[y].push_back(x);    }    init();    int cas,v,d;    w(q--)    {        scanf("%d%d",&cas,&v);        if(!cas)        {            scanf("%d%d",&x,&d);            updata(v,x,d);        }        else            printf("%d\n",query(v));    }    return 0;}





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.