cf 1076e 树上差分+树状数组+离线

http://codeforces.com/contest/1076/problem/E

参考博客:http://www.cnblogs.com/AKMer/p/9950332.html

题意:

根节点为1 树,m次操作,每次给定v,d,x,将v的儿子(包含其本身)与它距离<=d的权值加上x

问最后 所有节点的权值

思路:

离线操作

将m次操作保存,之后在dfs的时候用树状数组动态维护深度差分值

,然后单点询问当前深度应该增加多少就行了。如果本子树处理完了,那么就把差分去掉,以免影响其它子树。

注意:因为树状数组是以深度为基础的,所以对一个子树,其深度符合条件,就可以加上

     然后这个子树访问完毕,在用树状数组反差分回去


开始数组忘了*2     居然给mle而不是re....

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define low(i) ((i)&(-i))
const int N = 3e5+3;

int dep[N];int n;
ll ans[N];
vector<  pair<int,int >  >qu[N];
vector< pair<int,int > >::iterator it;
int y[N*2],fst[N],nxt[N*2];
int cnt;
void addedge(int a,int b){
    y[++cnt] =b;
    nxt[cnt] = fst[a];
    fst[a] = cnt;
}
struct TreeArray {
    ll c[N];
    void add(int pos,int v) {
        for(int i=pos;i<=n;i+=low(i))
            c[i]+=v;
    }
    ll query(int pos) {
        ll res=0;
        for(int i=pos;i;i-=low(i))
            res+=c[i];
        return res;
    }
}T;


void dfs(int x,int pre){
    dep[x] =dep[pre]+1;
    for(int i=fst[x];i;i=nxt[i]){
        if(y[i]!=pre)
            dfs(y[i],x);
    }
}

void get(int pre,int x){
    ////进来的时候差分
    for( it = qu[x].begin();it!=qu[x].end();++it){
        T.add(dep[x],(*it).se);
        //这里 是 r+1
        T.add(  min(n,dep[x]+(*it).fi)+1,-(*it).se);
    }

    ans[x] = T.query(dep[x]);
    for(int i=fst[x];i;i=nxt[i]){
        if(y[i]!=pre)get(x,y[i]);
    }
    //出去的时候反差分
    for( it = qu[x].begin();it!=qu[x].end();++it){
        T.add(dep[x],-(*it).se);
        //这里 是 r+1
        T.add(  min(n,dep[x]+ (*it).fi)+1,(*it).se);
    }
}

int main(){
    scanf("%d",&n);
    int v,u,m,d,x;
    for(int i=1;i<n;++i){
        scanf("%d %d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }

    dfs(1,0);

    scanf("%d",&m);
    while(m--){
        scanf("%d %d %d",&v,&d,&x);
        qu[v].push_back(  mp(d,x));
    }

    get(0,1);

    for(int i=1;i<=n;++i)
        printf("%lld ",ans[i]);

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wjhstudy/p/9991482.html
今日推荐