Educational Codeforces Round #54 (Div. 2) E. Vasya and a Tree 技巧題
Posted lin88
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round #54 (Div. 2) E. Vasya and a Tree 技巧題相关的知识,希望对你有一定的参考价值。
題目連接:http://codeforces.com/contest/1076/problem/E
本題大意:
給一棵根節點為“1”樹,給m個操作,每個操作三個整數,v,d,x,意思是從節點1,往下深度d,遍及的節點的值都加上x,d可能是0,就是只加在自己上。結束m個操作后輸出每個節點的值。
解題思路:
這裡不應該考慮同時操作整棵樹。因為每個節點的子樹是多樣的,而應該以dfs的形式,直接搜到葉子節點,這樣沿途就是一條鏈。每時每刻都在操作一條鏈,也就是一段區間。這樣操作轉化為:一個節點往後的距離為d的區間內都加上x,這樣問題就轉變成了區間修改的問題,利用樹狀數組來實現。
存在疑問的地方應該是,當搜不同的葉子節點的時候,鏈是不一樣的,如何鏈的變化。只要想一下,從一個葉子到另一個葉子,不就是區間修改——把前一個葉子的影響去掉,然後加上另一個葉子的影響不就好了嗎?也就是說,dfs回退是把回退掉的點的影響去掉,這在樹狀數組上實現就是回退時加上一個-x就好了。
下面是AC代碼:
1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int N=3e5+7;
5 struct Node
6 {
7 int v,next;
8 }a[N<<1];
9 struct Flag//記錄操作
10 {
11 int d,x;
12 };
13 int n,cnt;
14
15 int head[N];//前向星
16 inline void add(int u,int v)
17 {
18 a[cnt].v=v;
19 a[cnt].next=head[u];
20 head[u]=cnt++;
21 }
22
23 ll tr[N],ans[N];//樹狀數組,答案
24 inline void update(int x,int v)
25 {
26 for(;x<N;x+=x&-x)
27 tr[x]+=v;
28 }
29
30 inline ll sum(int x)
31 {
32 ll ret=0;
33 for(;x>0;x-=x&-x)
34 ret+=tr[x];
35 return ret;
36 }
37
38 vector<Flag> v[N];//存儲每個節點的操作
39 bool vis[N];
40 void dfs(int now,int dep)
41 {
42 vis[now]=1;
43 int nd,nx;
44
45 for(int i=0;i<v[now].size();++i)//讓當前節點的操作生效
46 {
47 nd=min(dep+v[now][i].d,n);
48 nx=v[now][i].x;
49 update(dep,nx);
50 update(nd+1,-nx);
51 }
52
53 ans[now]=sum(dep);//記錄當前節點的值
54
55 for(int i=head[now];i!=-1;i=a[i].next)//繼續往下
56 {
57 if(vis[a[i].v])
58 continue;
59 dfs(a[i].v,dep+1);
60 }
61
62 for(int i=0;i<v[now].size();++i)//回退時把在該節點生效的操作撤銷
63 {
64 nd=min(dep+v[now][i].d,n);
65 nx=v[now][i].x;
66 update(dep,-nx);//樹狀數組上加上負數
67 update(nd+1,nx);
68 }
69 }
70 int main()
71 {
72 int x,y;
73 memset(head,-1,sizeof(head));
74 scanf("%d",&n);
75 for(int i=1;i<n;++i)
76 {
77 scanf("%d%d",&x,&y);
78 add(x,y);
79 add(y,x);
80 }
81 int q;
82 scanf("%d",&q);
83 int t;
84 Flag temp;
85 for(int i=1;i<=q;++i)
86 {
87 scanf("%d%d%d",&t,&temp.d,&temp.x);//把操作裝到各點的vector里
88 v[t].push_back(temp);
89 }
90 dfs(1,1);
91 for(int i=1;i<n;++i)
92 printf("%lld ",ans[i]);
93 printf("%lld
",ans[n]);
94 }
以上是关于Educational Codeforces Round #54 (Div. 2) E. Vasya and a Tree 技巧題的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33