• Codeforces Round #225 (Div. 1) C-Propagating tree (DFS序+线段树/树状数组)


    题目链接:

    http://codeforces.com/problemset/problem/383/C

    题意:

    给出一颗有n个节点,且1为根节点的树,每个节点有它的权值,现在进行m次操作,操作分为添加和查询,当一个节点的权值添加v,则它的孩子节点的权值要添加-v,它的孩子的孩子节点+v, 以此类推。

    思路:

    来自: http://blog.csdn.net/qq978874169/article/details/51519719

    DFS标号后,按照深度分出奇偶层,当奇数(偶数)层+v时,对应偶数(奇数)层-v,两个线段树跑一跑就好。

    dfs序是把树压下去,变成一条直线,这样连续的一段直线就是一颗子树,而我们每次更新就是更新的(L[x],R[x])这段。

    维护两颗线段树,一颗代表奇数层,一颗对应偶数层,每次操作都可能给相应的层加或者减去,因为每次操作的树可能在奇数层上也可能在偶数层上。

    查询就是查询到叶子节点,返回这个叶子对应的奇数或者偶数层的数。

    树状数组也可以做,更新是对L[x]~最后更新一次+y, 再对R[x]+1~最后更新一次-y【更新回来】,这样就只更新了(L[x],R[x])

    对于查询x,是查询1~L[x],也就是这个点的所有祖先对x的影响,求和就是答案了。

    代码:

    线段树:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 2e5+10;
    17 
    18 vector<int> node[maxn];
    19 int val[maxn],n,m;
    20 int L[maxn],R[maxn],flag[maxn],lazy[2][maxn<<2],tot;
    21 
    22 void dfs(int u,int fa,int f){
    23     L[u] = ++tot;
    24     flag[u] = f;
    25     for(int i=0; i<(int)node[u].size(); i++){
    26         int v = node[u][i];
    27         if(fa == v) continue;
    28         dfs(v,u,f^1);
    29     }
    30     R[u] = tot;
    31 }
    32 
    33 void push_down(int rt){
    34     if(lazy[0][rt]){
    35         lazy[0][rt<<1] += lazy[0][rt];
    36         lazy[0][rt<<1|1] += lazy[0][rt];
    37     }
    38     if(lazy[1][rt]){
    39         lazy[1][rt<<1] += lazy[1][rt];
    40         lazy[1][rt<<1|1] += lazy[1][rt];
    41     }
    42     lazy[0][rt] = lazy[1][rt] = 0;
    43 }
    44 
    45 void update(int l,int r,int rt,int ql,int qr,int f,int val){
    46     if(ql<=l && r<=qr) {
    47         lazy[f][rt] += val; lazy[f^1][rt] -= val;
    48         return ;
    49     }
    50     push_down(rt);
    51     int mid = (l+r)/2;
    52     if(ql<=mid) update(l,mid,rt<<1,ql,qr,f,val);
    53     if(mid<qr) update(mid+1,r,rt<<1|1,ql,qr,f,val);
    54 }
    55 
    56 int query(int l,int r,int rt,int f,int p){
    57     if(l == r) return lazy[f][rt];
    58     push_down(rt);
    59     int mid = (l+r)/2;
    60     if(p <= mid) query(l,mid,rt<<1,f,p);
    61     else query(mid+1,r,rt<<1|1,f,p);
    62 }
    63 
    64 int main(){
    65     cin >> n >> m;
    66     for(int i=1; i<=n; i++)
    67         cin >> val[i];
    68     for(int i=1; i<n; i++){
    69         int x,y; cin>>x>>y;
    70         node[x].push_back(y);
    71         node[y].push_back(x);
    72     }
    73 
    74     tot = 0;
    75     dfs(1,-1,0);
    76 
    77     for(int i=0; i<m; i++){
    78         int op,x,y; cin>>op>>x;
    79         if(op==1){
    80             cin >> y;
    81             update(1,n,1,L[x],R[x],flag[x],y);
    82         }else{
    83             printf("%d
    ",val[x]+query(1,n,1,flag[x],L[x]));
    84         }
    85     }
    86 
    87     return 0;
    88 }

    树状数组:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 2e5+10;
    17 
    18 int n,m;
    19 vector<int> node[maxn];
    20 int tot,L[maxn],R[maxn],flag[maxn],val[maxn];
    21 int lazy[2][maxn<<2];
    22 
    23 void dfs(int u,int fa,int f){
    24     L[u] = ++tot;
    25     flag[u] = f;
    26     for(int i=0; i<(int)node[u].size(); i++){
    27         int v = node[u][i];
    28         if(v == fa) continue;
    29         dfs(v,u,f^1);
    30     }
    31     R[u] = tot;
    32 }
    33 
    34 void add(int x,int f,int val){
    35     while(x<=n){
    36         lazy[f][x] += val;
    37         lazy[f^1][x] -= val;
    38         x += x&-x;
    39     }
    40 }
    41 
    42 int que(int x,int f){
    43     int res = 0;
    44     while(x){
    45         res += lazy[f][x];
    46         x -= x&-x;
    47     }
    48     return res;
    49 }
    50 
    51 int main(){
    52     cin >> n >> m;
    53     for(int i=1; i<=n; i++)
    54         cin >> val[i];
    55     for(int i=1; i<n; i++){
    56         int x,y; cin>>x>>y;
    57         node[x].push_back(y);
    58         node[y].push_back(x);
    59     }
    60     tot = 0;
    61     dfs(1,-1,0);
    62 
    63     for(int i=0; i<m; i++){
    64         int op,x,y;
    65         cin >> op >> x;
    66         if(op == 1){
    67             cin >> y;
    68             add(L[x],flag[x],y);
    69             add(R[x]+1,flag[x],-y);
    70         }else{
    71             printf("%d
    ",val[x]+que(L[x],flag[x]));
    72         }
    73     }
    74 
    75     return 0;
    76 }
  • 相关阅读:
    hdu4829 带权并查集(题目不错)
    hdu4829 带权并查集(题目不错)
    洛谷 P1076 寻宝(模拟 && 剪枝)
    洛谷 P1981 表达式求值(模拟)
    洛谷 P2239 螺旋矩阵(模拟 && 数学)
    洛谷 P2118 比例简化(枚举)
    洛谷 P3956 棋盘(记忆化搜索)
    洛谷 P5018 对称二叉树(搜索)
    洛谷 P5016 龙虎斗(模拟)
    洛谷 P1563 玩具谜题(模拟)
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6937924.html
Copyright © 2020-2023  润新知