1076E/Educational Codeforces Round 54-E. Vasya and a Tree<<dfs序 树状数组

题意

给定一棵树,初始每个节点权值为零,q次更改,每次修改将以v为顶点的深度为d的子树全部加上x,最后输出所有节点的权重。

思路

题目只要求每个点最后的值,那么经过观察,发现一个点最后的权值大小只与他的父节点的更新有关,那么我们就只需要考虑他的父节点到他这条链上的情况,把这条链拿出来成为线段,然后维护后缀和就能得到此点上的权值。每个节点的贡献为给$[h,h+d]$增加$x$,所以维护时,只要在$h+d$点上加上$x$即可。

但是问题考察的是一棵树,我们就需要动态来完成这条链,我们采用dfs序去扫描这棵树,当一个节点进入时,把他的贡献算上,退出时减去他的贡献,这样就能保证他不会影响别的链。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef pair<int,int> PII;
 4 const int maxn=3e5+7;
 5 vector<PII> query[maxn];
 6 vector<int> G[maxn];
 7 long long tree[maxn];
 8 long long ans[maxn];
 9 int depth[maxn],reflect[maxn];
10 int st[maxn],ed[maxn];
11 void dfs(int now,int far)
12 {
13     static int tot=0;
14     st[now]=++tot;
15     reflect[tot]=now;
16     if(far==-1)
17     {
18         depth[now]=1;
19     }
20     for(int i=0;i<G[now].size();i++)
21     {
22         int v=G[now][i];
23         if(v==far) continue;
24         depth[v]=depth[now]+1;
25         dfs(v,now);
26     }
27     ed[now]=tot;
28 }
29 void add(int x,int v)
30 {
31     while(x<maxn)
32     {
33         tree[x]+=v;
34         x+=x&-x;
35     }
36 }
37 long long sum(int x)
38 {
39     long long ret=0;
40     while(x>0)
41     {
42         ret+=tree[x];
43         x-=x&-x;
44     }
45     return ret;
46 }
47 int main()
48 {
49     int n;
50     memset(tree,0,sizeof(tree));
51     scanf("%d",&n);
52     for(int i=1,u,v;i<=n-1;i++)
53     {
54         scanf("%d%d",&u,&v);
55         G[u].push_back(v);
56         G[v].push_back(u);
57     }
58     dfs(1,-1);//跑出dfs序
59     int q;
60     scanf("%d",&q);
61     while(q--)//存储所有询问,将他们按节点分开转换为dfs序的树上顺序
62     {
63         int v,d,x;
64         scanf("%d%d%d",&v,&d,&x);
65         d+=depth[v];
66         d=min(d,n);
67         query[st[v]].push_back(make_pair(d,x));
68         query[ed[v]+1].push_back(make_pair(d,-x));//在退出时清除贡献
69     }
70     for(int i=1;i<=n;i++)
71     {
72         for(int j=0;j<query[i].size();j++)//把这个节点上更新的都更新了
73         {
74             PII temp=query[i][j];
75             add(temp.first,temp.second);
76         }
77         ans[reflect[i]]=sum(n)-sum(depth[reflect[i]]-1);//映射返回得到答案
78     }
79     for(int i=1;i<=n;i++)
80     {
81         printf("%lld ",ans[i]);
82     }
83 }

原文地址:https://www.cnblogs.com/computer-luo/p/9970985.html

时间: 2024-08-08 13:54:39

1076E/Educational Codeforces Round 54-E. Vasya and a Tree<<dfs序 树状数组的相关文章

Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/problem/C Description Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numb

Codeforces Round #227 (Div. 2)---E. George and Cards(贪心, 树状数组+set维护, 好题!)

George is a cat, so he loves playing very much. Vitaly put n cards in a row in front of George. Each card has one integer written on it. All cards had distinct numbers written on them. Let's number the cards from the left to the right with integers f

Codeforces Round #609 (Div. 2)E--K Integers(贪心+二分+树状数组+逆序对)

K Integers 参考博客:https://blog.csdn.net/Q755100802/article/details/103664555 [题意] 给定一个1到n的排列,可以交换相邻的两个元素. 现在定义一个函数f(x),表示在原排列中,通过交换操作,形成一个1,2,3....x的排列的子串,需要的最小操作步骤. 子串意味着这个排列必须是相邻的.现在你需要求出f(1),f(2),f(3)......f(n). [分析] 在1~x这几个元素相邻的情况下,因为最后排列不存在逆序对,根据贪

Codeforces 570D TREE REQUESTS dfs序+树状数组 异或

http://codeforces.com/problemset/problem/570/D Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of?n?vertices. Each vertex contains a lowercase

CodeForces 570D DFS序 树状数组 Tree Requests

参考九野巨巨的博客. 查询一个子树内的信息,可以通过DFS序转成线形的,从而用数据结构来维护. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 #define MP make_pair 7 #define FI first 8 #define SE second 9 using name

Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum 树状数组

D. Mishka and Interesting sum 链接: http://codeforces.com/problemset/problem/703/D 题意: 给一个序列 每次询问一个区间 求区间中出现次数为偶数次的数的异或和 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<map> 5 using namespace std; 6 7 str

343D/Codeforces Round #200 (Div. 1) D. Water Tree dfs序+数据结构

D. Water Tree Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a reservoir which can be either empty or filled with water. The vertices of the tree are numbered from 1 to n with the root at vertex 1. For

Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum 树状数组+离线

D. Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabytes input standard input output standard output Little Mishka enjoys programming. Since her birthday has just passed, her friends decided to present her wit

Codeforces 570D TREE REQUESTS dfs序+树状数组

链接 题解链接:点击打开链接 题意: 给定n个点的树,m个询问 下面n-1个数给出每个点的父节点,1是root 每个点有一个字母 下面n个小写字母给出每个点的字母. 下面m行给出询问: 询问形如 (u, deep) 问u点的子树中,距离根的深度为deep的所有点的字母能否在任意排列后组成回文串,能输出Yes. 思路:dfs序,给点重新标号,dfs进入u点的时间戳记为l[u], 离开的时间戳记为r[u], 这样对于某个点u,他的子树节点对应区间都在区间 [l[u], r[u]]内. 把距离根深度相