ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang(树状数组+分块)

Given a rooted tree ( the root is node 1 ) of N nodes. Initially, each node has zero point.

Then, you need to handle Q operations. There're two types:

1 L X: Increase points by X of all nodes whose depth equals L ( the depth of the root is zero ). (x≤108)

2 X: Output sum of all points in the subtree whose root is X.

Input
Just one case.

The first lines contain two integer, N,Q(N≤105,Q≤105).

The next n−1 lines: Each line has two integer aaa,bbb, means that node aaa is the father of node b. It's guaranteed that the input data forms a rooted tree and node 1 is the root of it.

The next Q lines are queries.

Output
For each query 2, you should output a number means answer.

样例输入
3 3
1 2
2 3
1 1 1
2 1
2 3

样例输出
1
0

题意

给你一颗以1为根节点的数,有两个操作

1.层数为L的节点增加X

2.查询以X为根节点的子树总权和

题解

操作2很容易想到dfs维护树状数组

对于操作1,可以把层数按sqrt(n)分块,对于层数点数<=block的直接暴力更新,对于>block先保存进数组ans,查询的时候二分左右区间可以知道根的节点数,再乘ans,这样可以把单次操作的复杂度固定在sqrt(n)范围内

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define LL long long
 5 
 6 const int maxn=1e5+5;
 7 int s[maxn],e[maxn],tot,n;
 8 LL sum[maxn],ans[maxn];
 9 vector<int>G[maxn],deep[maxn],q;
10 void dfs(int u,int fa,int d)
11 {
12     s[u]=++tot;
13     deep[d].push_back(s[u]);
14     for(auto v:G[u])
15     {
16         if(v==fa)continue;
17         dfs(v,u,d+1);
18     }
19     e[u]=tot;
20 }
21 int lowbit(int x)
22 {
23     return x&(-x);
24 }
25 void update(int x,int add)
26 {
27     for(int i=x;i<=n;i+=lowbit(i))
28         sum[i]+=add;
29 }
30 LL query(int x)
31 {
32     LL ans=0;
33     for(int i=x;i>0;i-=lowbit(i))
34         ans+=sum[i];
35     return ans;
36 }
37 int main()
38 {
39     int Q,op,L,x,u,v;
40     scanf("%d%d",&n,&Q);
41     int block=sqrt(n);
42     for(int i=1;i<n;i++)
43     {
44         scanf("%d%d",&u,&v);
45         G[u].push_back(v);
46         G[v].push_back(u);
47     }
48     dfs(1,-1,0);
49     for(int i=0;i<n;i++)
50         if(deep[i].size()>block)q.push_back(i);
51     for(int i=0;i<Q;i++)
52     {
53         scanf("%d",&op);
54         if(op==1)
55         {
56             scanf("%d%d",&L,&x);
57             if(deep[L].size()>block)ans[L]+=x;
58             else
59             {
60                 for(auto X:deep[L])
61                     update(X,x);
62             }
63         }
64         else
65         {
66             scanf("%d",&x);
67             LL res=query(e[x])-query(s[x]-1);
68             for(auto pos:q)
69                 res+=ans[pos]*(upper_bound(deep[pos].begin(),deep[pos].end(),e[x])-lower_bound(deep[pos].begin(),deep[pos].end(),s[x]));
70             printf("%lld\n",res);
71         }
72     }
73     return 0;
74 }

 

posted on 2018-09-15 09:42  大桃桃  阅读(251)  评论(0编辑  收藏  举报

导航