1. 程式人生 > >【Educational Codeforces Round 54 (Rated for Div. 2) E. Vasya and a Tree】 dfs+樹狀陣列

【Educational Codeforces Round 54 (Rated for Div. 2) E. Vasya and a Tree】 dfs+樹狀陣列

E. Vasya and a Tree

題意

n

0
給你一顆n個點的樹,每個點的權值最初為0
m
v , d , x 有m個操作,每次操作有三個變數v,d,x

v v < = d + x 操作為在v的距離v<=d的子樹內所有節點權值+x
最終統計樹上每個點的權值

做法

首先要明確兩件事情
1. ( ) 性質1.每個人的操作只會影響到他的子孫(包括自己)
2. ( ) 性質2.每個人只會被他祖先的操作所影響(包括自己)
也就是說,如果我們能在訪問到某個節點時,統計出所有影響到該節點的祖先操作
就可以統計出這個節點的最終權值
d e p 而對於每個操作,我們只要用一個dep陣列儲存每個深度被增加的值
所有深度大於當前節點的操作都會影響到當前節點,如果用線段樹就是一個區間求和問題
為了減少程式碼量我們用樹狀陣列,更新時只在本次操作的最深的深度更新
1 m a x d e p 這樣求一個1-maxdep的字首和就是所有更新了根節點的操作
1 ( n o w d e p 1 ) 在求一個1-(nowdep-1)的字首和就是所有不包含當前節點的操作
兩個字首和相減就是當前節點被更新的值
d f s 退 為了保證每個操作隻影響自己子樹內的節點,在dfs退出子樹時
要將當前根節點的所有修改值還原

程式碼

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 3e5+10;
int n,m;
ll tree[maxn],ans[maxn];
vector<int> G[maxn],D[maxn],X[maxn];
void add(int x,int val)
{
    while(x<=n)
    {
        tree[x]+=val;
        x=x+(x&-x);
    }
}
ll sum(int x)
{
    ll ans=0;
    while(x)
    {
        ans+=tree[x];
        x=x-(x&-x);
    }
    return ans;
}
void dfs(int x,int fa,int dep)
{
    for(int i=0;i<D[x].size();i++)
    {
        add(min(D[x][i]+dep,n),X[x][i]);//進子樹之前更新
    }
    ans[x]=sum(n)-sum(dep-1);//樹狀陣列變區間查詢為兩個字首和相減
    //由於性質2,所以在這個地方就可以直接算出當前節點的最終答案
    for(int i=0;i<G[x].size();i++)
    {
        if(G[x][i]==fa) continue;
        dfs(G[x][i],x,dep+1);
    }
    for(int i=0;i<D[x].size();i++)
    {
        add(min(D[x][i]+dep,n),-X[x][i]);//出子樹之後還原
    }
}
int main()
{
    int x,y,z;
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        D[x].push_back(y);
        X[x].push_back(z);
    }
    dfs(1
            
           

相關推薦

Educational Codeforces Round 54 (Rated for Div. 2) E. Vasya and a Tree dfs+陣列

HEU 大三蒟蒻一枚 有任何問題或建議都可以加Q聯絡我^_^ QQ : 986195894 CodeForces id : lajiyuan CodeForces id : biubiubiu_ Vjudge id : heu2016201206

Educational Codeforces Round 54 (Rated for Div. 2) E. Vasya and a Tree(dfs+思維)

E. Vasya and a Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

Educational Codeforces Round 56 (Rated for Div. 2) E. Intersection of Permutations(分塊 + 陣列

題目連結:https://codeforces.com/contest/1093/problem/E 題目大意:給出兩個1~n的排列 a 和 b;對這兩個排列進行如下兩種操作: 1 la ra lb rb:查詢排列 a 的區間 [la,ra]

Educational Codeforces Round 53 (Rated for Div. 2)-C. Vasya and Robot二分

Educational Codeforces Round 53 (Rated for Div. 2) C. Vasya and Robot 題意 在 二

Educational Codeforces Round 51 (Rated for Div. 2)E. Vasya and Big Integers(二分雜湊+差分)

題目傳送門 題意   給出長度小於等於10610^6106的數字串a,l,r,求把串a拆分後,每段數字大小都是≥l\geq l≥l並且≤r\leq r≤r的方案有多少種。 分析   首先我們可以發現一個很顯然的結論,即如果從第i位開始截成一段,那麼這一

Educational Codeforces Round 53 (Rated for Div. 2) C. Vasya and Robot 二分 + 尺取

任意門:http://codeforces.com/contest/1073/problem/C C. Vasya and Robot time limit per test 1 second memory limit per test

Educational Codeforces Round 55 (Rated for Div. 2) B. Vova and Trophies暴力+細節題

B. Vova and Trophies 題意 給你一個只有G,S兩種字元的字串,可以交換一次兩個位置的字元,問最終最長的連續的G可以有多少個 2

Educational Codeforces Round 55 (Rated for Div. 2) E. Increasing Frequency滾動陣列優化暴力

E. Increasing Frequency 題意 給你一個數列,你可以選擇在[l,r]區間同時加或者減一個值, 在一次操作後,這個序列最多有多少個值等於c 做法 首先我們要想明白的是,a[l]一定是等於a[r]的 如果a[l]!=a[r],那麼我們肯定可以縮小這個區間,

Educational Codeforces Round 44 (Rated for Div. 2)+E. Pencils and Boxes+數組

namespace 超過 closed .com 樹狀數組 最小 %d lse pre 題目鏈接:E. Pencils and Boxes 題意:N 個數,要求分成任意堆,要求每一堆只要有K個,同一堆中任意數之間差值不能超過d; 題解:用樹狀數組。排一下序然後從後面開始

Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

problem 滿足 names fort determine resp binary nat 題意 Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 題目

Educational Codeforces Round 53 (Rated for Div. 2) C. Vasya and Robot(二分+模擬)

題目連結 題意 一個二維平面上有個機器人初始在 ( 0 ,

Educational Codeforces Round 53 (Rated for Div. 2) C. Vasya and Robot 二分+前後綴預處理

題意: 給定長度為n的字串,每個字元表示朝上下左右四個方向前進,給定一個目標位置,找一個最小的區間,使得改變這個區間的若干個字元,使得整個串的操作能到達目標位置只需要輸出最小區間長度 思路: 首先暴力的想法就是列舉所有的區間,這樣這個區間兩邊就會有一些操作不會改變,然後我們根據這些操

Educational Codeforces Round 52 (Rated for Div. 2)B. Vasya and Isolated Vertices·「模擬,思維」

B. Vasya and Isolated Vertices time limit per test 1 second memory limit per test 256 megabytes input standard input output standard o

Educational Codeforces Round 52 (Rated for Div. 2) B. Vasya and Isolated Vertices

題解 題目大意 給你n個點使用m條邊組成一個圖 問你最多和最小能有多少個孤立節點(度為0) 最少的點個數就是每個邊連兩個點m-n2和0取max 最多的點計算d(d-1)=m*2用n-d 需要特判0 AC程式碼 #include <stdio.h> #

Educational Codeforces Round 53 (Rated for Div. 2)-C. Vasya and Robot

思路:一開始做思路就錯了,我考慮的是如何轉變方向使其有效到達目標位置,但是比較複雜。這題要求更改的區間最小長度。因此可以二分割槽間長度,在遍歷左端點看是否存在即可。判斷存在,即更改的區間的個數是否能將其他區域的缺少或多餘步驟給消掉即可。 Code: #includ

Educational Codeforces Round 54 (Rated for Div. 2) B. Divisor Subtraction

觀察易得 1.質數無1和自身外的因子 且只有本身既質又因 按題意直接一步減自身至零 2.若N是偶數則一直減2直到0 所有質數都是奇數 奇數減奇數易得偶數 再回到條件2 一步到位 所以操作次數不會太多 線篩打表 結合1 2 暴力模擬即可   /* Z