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\n",ans[n]);
94 }

原文地址:https://www.cnblogs.com/Lin88/p/9973575.html

时间: 2024-10-16 15:52:51

Educational Codeforces Round #54 (Div. 2) E. Vasya and a Tree 技巧題的相关文章

Codeforces Round #262 (Div. 2)460A. Vasya and Socks(简单数学题)

题目链接:http://codeforces.com/contest/460/problem/A A. Vasya and Socks time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Vasya has n pairs of socks. In the morning of each day Vasya has to put o

Codeforces Round #319 (Div. 2) C Vasya and Petya&#39;s Game

因为所有整数都能被唯一分解,p1^a1*p2^a2*...*pi^ai,而一次询问的数可以分解为p1^a1k*p2^a2k*...*pi^aik,这次询问会把所有a1>=a1k && a2 >= a2k &&... a3 >= a3k的数从原来的集合中分开.ai表示pi的幂. 那么只有当这个数的素因子的最大幂都被询问过一次,这个数才能确定.因此答案是所有的不大于n的只有一个素因子的数. #include<bits/stdc++.h> using

Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree(树上Nim)

题目链接:Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree 题意: 给你一棵树,每个节点有a[i]个苹果,有两个人要在这个树上玩游戏. 两个人轮流操作,谁不能操作谁就输了. 这个树有一个特性:叶子到根的距离的奇偶性相同. 每次操作可以选一个节点i,和一个数x,x小于当前节点i的苹果数. 对于节点i,如果是叶子节点,就将这x个苹果吃掉. 如果是非叶子节点,就将这x个苹果移向节点i的任意儿子节点. 现在第二个操作的人要交换两个节点的苹果

Codeforces Educational Codeforces Round 54 题解

题目链接:https://codeforc.es/contest/1076 A. Minimizing the String 题意:给出一个字符串,最多删掉一个字母,输出操作后字典序最小的字符串. 题解:若存在一个位置 i 满足 a[i] > a[i+1],若不删除 a[i] 则后续操作不可能更优. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned

Educational Codeforces Round 54 (Rated for Div. 2) D Edge Deletion (SPFA + bfs)

题目大意:给定你一个包含n个点m条边的无向图,现在最多在图中保留k条边,问怎么删除多的边,使得图中良好的节点数最多,求出保留在图中的边的数量和编号. 良好的节点定义为:删除某条边后该点到点1的最短距离不变. 思路:先求出所有点到点1的最短距离,之后再bfs一遍,若遍历到某一节点时的距离等于该点到点1的最短距离就将该条边加进去,直到添加到k条边或者遍历结束.(虽然过了但是还是觉得有有的情况好像过不了,但是没想出来...可能数据还有点水..) 一开始INF值设小了WA了四次... INF值设置1e1

codeforces水题100道 第十五题 Codeforces Round #262 (Div. 2) A. Vasya and Socks (brute force)

题目链接:http://www.codeforces.com/problemset/problem/460/A题意:Vasya每天用掉一双袜子,她妈妈每m天给他送一双袜子,Vasya一开始有n双袜子,请问第几天的时候Vasya会没有袜子穿?C++代码: #include <iostream> using namespace std; int n, m; int main() { cin >> n >> m; int d = 0; while (n) { d ++; if

Codeforces Round #281 (Div. 2) A. Vasya and Football 暴力

A. Vasya and Football Vasya has started watching football games. He has learned that for some fouls the players receive yellow cards, and for some fouls they receive red cards. A player who receives the second yellow card automatically receives a red

Codeforces Round #281 (Div. 2) C. Vasya and Basketball 排序

C. Vasya and Basketball Vasya follows a basketball game and marks the distances from which each team makes a throw. He knows that each successful throw has value of either 2 or 3 points. A throw is worth 2 points if the distance it was made from does

Codeforces Round #281 (Div. 2) B. Vasya and Wrestling 水题

B. Vasya and Wrestling Vasya has become interested in wrestling. In wrestling wrestlers use techniques for which they are awarded points by judges. The wrestler who gets the most points wins. When the numbers of points of both wrestlers are equal, th