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:
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?≤?n, ui?≠?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 numbers in the lines are separated by single spaces.
For each request to print the node value print an integer — the reply to the request.
3 6 1 2 1 3 0 3 1 2 0 2 3 1 0 1 5 2 1 1 1 2 1 3
9 9 6
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
11 17 11 16 17 11
题意:一棵树只有一个顶点,然后由这个顶点引申出多条链,对于输入 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 long const double pi = acos(-1.0); #define N 100005 #define mod 19999997 const 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; }
Codeforces276E:Little Girl and Problem on Trees
原文地址:http://blog.csdn.net/libin56842/article/details/45490961