zoukankan      html  css  js  c++  java
  • codeforces 1076E Vasya and a Tree 【dfs+树状数组】

    题目:戳这里

    题意:给定有n个点的一棵树,顶点1为根。m次操作,每次都把以v为根,深度dep以内的子树中所有的顶点(包括v本身)加x。求出最后每个点的值为多少。

    解题思路:考虑到每次都只对点及其子树操作,要用dfs。设v当前要操作的点,操作的深度是dep,d[v]表示v的深度。要把深度[d[v],d[v]+dep]中所有点都加上x,暴力加是肯定不行的,于是想到要用树状数组或线段树。dfs+树状数组便是本题的基本思路。我们在搜索树的同时,维护以深度为下标的树状数组。为什么一个树形结构能够维护树状数组这样的线性结构呢?因为是对树的dfs,只要没有跳出点就一定搜一条线到底,这样搜索出来的点就能满足树状数组的线性。而每当跳出一个点,就把这个点给树状数组加的值减掉(回溯)即可。

    附本人代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <vector>
     5 #define lowbit(x) x&-x
     6 typedef long long ll;
     7 const int maxn = 3e5+10;
     8 const ll inf = 1e18;
     9 using namespace std;
    10 ll c[maxn];
    11 vector<int> eg[maxn],dep[maxn];
    12 vector<ll> op[maxn];
    13 ll ans[maxn];
    14 int n, m;
    15 void add(int x, ll u) {
    16     while(x <= n) {
    17         c[x] += u;
    18         x += lowbit(x);
    19     }
    20 }
    21 ll sum(int x) {
    22     ll res = 0;
    23     while(x > 0) {
    24         res += c[x];
    25         x -= lowbit(x);
    26     }
    27     return res;
    28 }
    29 void dfs(int now, int pre, int d) {
    30     for(int i = 0; i < op[now].size(); ++i) {
    31         add(min(d + dep[now][i], n), op[now][i]);
    32     }
    33     ans[now] = sum(n) - sum(d-1);
    34     for(auto i: eg[now]) {
    35         if(i == pre) continue;
    36         dfs(i, now, d+1);
    37     }
    38     for(int i = 0; i < op[now].size(); ++i) {
    39         add(min(d + dep[now][i], n), -op[now][i]);
    40     }
    41 }
    42 int main(){
    43 
    44     scanf("%d", &n);
    45     int x, y;
    46     for(int i = 1; i < n; ++i) {
    47         scanf("%d %d", &x, &y);
    48         eg[x].push_back(y);
    49         eg[y].push_back(x);
    50     }
    51     scanf("%d", &m);
    52     int v, d;
    53     ll xi;
    54     for(int i = 1; i <= m; ++i) {
    55         scanf("%d %d %lld", &v, &d, &xi);
    56         if(d > n) d = n;
    57         dep[v].push_back(d);
    58         op[v].push_back(xi);
    59     }
    60     dfs(1,0,1);
    61     for(int i = 1; i <= n; ++i)
    62     printf("%lld ", ans[i]);
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    简单测试
    纸玫瑰
    Java 字符串编码 (保存成txt测试)
    创建 Filter
    jee中文名图片+tomcat ==> 中文乱码的另类处理(未成功)
    dom4j_01_02
    dom4j_01_01
    Java 字符串编码
    websocket

  • 原文地址:https://www.cnblogs.com/zmin/p/9960834.html
Copyright © 2011-2022 走看看