zoukankan      html  css  js  c++  java
  • CF 1076E Vasya and a Tree(dfs+树状数组)

    链接:http://codeforces.com/problemset/problem/1076/E

    题意:给你一颗以1为根节点的树,初始所有节点的权值为0,然后有m个操作,每个操作将点v的儿子节点中和本身的所有距离不超过d的节点权值加x,问经过m次操作后,输出每个节点的权值。

    题解:如果是一个序列,就可以直接用树状数组做,但这是一颗树,所以我们可以想办法把它转化成序列。我们可以先求出每个节点的dfs序,以及深度和子树的大小,顺便记录每个深度都有哪些节点,子树的大小用来确认以该节点为根的子树在dfs序中的范围,此时便可用树状数组维护了。之后,我们把每个操作按能影响到的深度从大到小排序,即优先处理影响深度大的操作。设当前计算的深度为now,假设所有操的作影响的深度大于now的操作已经计算。如果当前操作影响的深度小于now,说明所有能影响到now深度的操作已经全部操作完了,此时把所有深度为now的节点权值计算出来。每读取一个操作的信息,就把操作产生的影响用树状数组维护,因为影响now深度的节点权值已经计算完毕了,所以我把以该操作的操作节点为根的子树全部加上操作的值 对之前已经计算的答案没有影响。操作全部完成后,深度从深到浅计算答案即可。

    代码:

    #include <bits/stdc++.h>
    #define IO_read ios::sync_with_stdio(false);cin.tie(0)
    #define fre freopen("in.txt", "r", stdin)
    #define _for(i,a,b) for(int i=a; i< b; i++)
    #define _rep(i,a,b) for(int i=a; i<=b; i++)
    using namespace std;
    typedef long long ll;
    #define lowbit(a) ((a)&-(a))
    
    const int maxn=3e5+5;
    
    int tot, head[maxn*2];
    struct Edge{
        int to, next;
    }edge[maxn*2];
    
    void addedge(int u, int v)
    {
        edge[++tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot;
    }
    
    int n, m;
    int deep[maxn], dfsn[maxn], sz[maxn];
    int max_deep, cnt_dfs;
    vector<int> vec[maxn];
    
    void dfs(int u, int now_deep)
    {
        max_deep=max(max_deep, now_deep);
        sz[u]=1, deep[u]=now_deep, dfsn[u]=++cnt_dfs;
        vec[now_deep].push_back(u);
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to;
            if(dfsn[v]) continue;  //连了2次边,要判断
            dfs(v, now_deep+1);
            sz[u]=sz[u]+sz[v];
        }
    }
    
    struct Opt{
        int rt, d, x;
        bool operator <(const Opt &a)const{
            return deep[rt]+d>deep[a.rt]+a.d;
        }
    }opt[maxn];
    
    ll tree[maxn], ans[maxn];
    
    void add(int x, int val)
    {
        for(int i=x; i<=n; i+=lowbit(i))
            tree[i]+=val;
    }
    
    ll ask(int x)
    {
        ll res=0;
        for(int i=x; i; i-=lowbit(i))
            res+=tree[i];
        return res;
    }
    
    int main()
    {
        IO_read;
        //fre;
        memset(head, -1, sizeof(head));
        cin>>n;
        _rep(i, 1, n-1)
        {
            int u, v;
            cin>>u>>v;
            addedge(u, v);
            addedge(v, u);
        }
        
        cin>>m;
        _rep(i, 1, m)
            cin>>opt[i].rt>>opt[i].d>>opt[i].x;
        dfs(1, 1);  //注意后面的排序用到了deep数组,所以要先dfs,在排序
        sort(opt+1, opt+1+m);
        
        int now_deep=max_deep;
        _rep(i, 1, m)
        {
            int rt=opt[i].rt, d=opt[i].d, x=opt[i].x;
            while(deep[rt]+d<now_deep)
            {
                for(int j=0; j<vec[now_deep].size(); j++)
                {
                    int v=vec[now_deep][j];
                    ans[v]=ask(dfsn[v]);
                }
                now_deep--;
            }
            add(dfsn[rt], x);
            add(dfsn[rt]+sz[rt], -x);
        }
        while(now_deep)  //注意这样写deep从1开始
        {
            for(int j=0; j<vec[now_deep].size(); j++)
            {
                int v=vec[now_deep][j];
                ans[v]=ask(dfsn[v]);
            }
            now_deep--;
        }
        _rep(i, 1, n)
            cout<<ans[i]<<" ";
        return 0;
    }
  • 相关阅读:
    bootstrap学习笔记
    java-多态
    java-重写
    java-继承
    java-包
    java-封装
    java-可变参数
    java-标准输入
    java-构造方法
    private、public、this关键字
  • 原文地址:https://www.cnblogs.com/Yokel062/p/11720881.html
Copyright © 2011-2022 走看看