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 }
  • 相关阅读:
    UIView
    UISwitch
    UIButton
    label标签的属性
    sublime 生成网页头文件
    Xcode快捷键
    Bootstrap 模态对话框只加载一次 remote 数据的解决办法 转载
    用谷歌浏览器来当手机模拟器
    DDD:谈谈数据模型、领域模型、视图模型和命令模型
    MoQ(基于.net3.5,c#3.0的mock框架)简单介绍
  • 原文地址:https://www.cnblogs.com/Lin88/p/9973575.html
Copyright © 2011-2022 走看看