zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Oracle 11g SQL Fundamentals Training Introduction02
    Chapter 05Reporting Aggregated data Using the Group Functions 01
    Chapter 01Restriicting Data Using The SQL SELECT Statemnt01
    Oracle 11g SQL Fundamentals Training Introduction01
    Chapter 04Using Conversion Functions and Conditional ExpressionsConditional Expressions
    Unix时代的开创者Ken Thompson (zz.is2120.bg57iv3)
    我心目中计算机软件科学最小必读书目 (zz.is2120)
    北京将评估分时分区单双号限行 推进错时上下班 (zz)
    佳能G系列领军相机G1X
    选购单反相机的新建议——心民谈宾得K5(转)
  • 原文地址:https://www.cnblogs.com/Lin88/p/9973575.html
Copyright © 2011-2022 走看看