• 【30.36%】【codeforces 740D】Alyona and a tree


    time limit per test2 seconds
    memory limit per test256 megabytes
    inputstandard input
    outputstandard output
    Alyona has a tree with n vertices. The root of the tree is the vertex 1. In each vertex Alyona wrote an positive integer, in the vertex i she wrote ai. Moreover, the girl wrote a positive integer to every edge of the tree (possibly, different integers on different edges).

    Let’s define dist(v, u) as the sum of the integers written on the edges of the simple path from v to u.

    The vertex v controls the vertex u (v ≠ u) if and only if u is in the subtree of v and dist(v, u) ≤ au.

    Alyona wants to settle in some vertex. In order to do this, she wants to know for each vertex v what is the number of vertices u such that v controls u.

    Input
    The first line contains single integer n (1 ≤ n ≤ 2·105).

    The second line contains n integers a1, a2, …, an (1 ≤ ai ≤ 109) — the integers written in the vertices.

    The next (n - 1) lines contain two integers each. The i-th of these lines contains integers pi and wi (1 ≤ pi ≤ n, 1 ≤ wi ≤ 109) — the parent of the (i + 1)-th vertex in the tree and the number written on the edge between pi and (i + 1).

    It is guaranteed that the given graph is a tree.

    Output
    Print n integers — the i-th of these numbers should be equal to the number of vertices that the i-th vertex controls.

    Examples
    input
    5
    2 5 1 4 6
    1 7
    1 1
    3 5
    3 6
    output
    1 0 1 0 0
    input
    5
    9 7 8 6 5
    1 1
    2 1
    3 1
    4 1
    output
    4 3 2 1 0
    Note
    In the example test case the vertex 1 controls the vertex 3, the vertex 3 controls the vertex 5 (note that is doesn’t mean the vertex 1 controls the vertex 5).

    【题目链接】:http://codeforces.com/contest/740/problem/D

    【题解】

    可以用一个类似”前缀长度”的东西来搞;
    设dis[x]表示根节点到x节点上的边权和.
    则x这个节点是被u节点控制的,当且仅当
    dis[x]-dis[u]<=a[x];
    即dis[x]-a[x] <= dis[u];
    而dis这个数组如果在dfs序上,肯定是单调递增的.
    所以维护一下dfs序、维护一下dis数组;
    在处理x的出度的时候
    找出dis数组中第一个满足dis[x]-a[x]<=dis[u]
    的u节点;
    则u->x的路径上的所有点都能够控制x节点.
    而u节点以上的节点都不能控制x节点.
    设u节点的dfs序的上一个节点为y
    则让ans[y]–;
    然后在dfs的时候累加答案即可;
    设当前节点为x,出度节点为y
    则ans[x]+=ans[y];
    当遇到那些ans被减过的节点(即执行过ans[x]–的节点x);
    则在算的时候就会把那个不属于它的节点给扣掉.
    而以上的节点相应的也会受“ans[x]–”的也不会算那些不属于它们的节点了.
    一开始让ans[x]都等于1;
    最后再减去1即可.
    这个方法很巧妙。
    如果不理解就多想想吧.

    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    #define all(x) x.begin(),x.end()
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int MAXN = 2e5+10;
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    
    int n;
    LL a[MAXN];
    LL ans[MAXN],dis[MAXN];
    vector <LL> w[MAXN];
    vector <int> G[MAXN];
    vector < pair<LL,int> > temp;
    
    void dfs(int x,int fa)
    {
        ans[x] = 1;
        LL t = dis[x]-a[x];
        int pos = lower_bound(all(temp),mp(t,0))-temp.begin();
        pos--;
        if (pos >= 0)
            ans[temp[pos].se]--;
        temp.pb(mp(dis[x],x));
        int len = G[x].size();
        rep1(i,0,len-1)
        {
            int y = G[x][i];
            if (y==fa) continue;
            dis[y] = dis[x] + w[x][i];
            dfs(y,x);
            ans[x] += ans[y];
        }
        temp.pop_back();
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        rei(n);
        rep1(i,1,n)
            rel(a[i]);
        rep1(i,2,n)
        {
            int fa;LL cost;
            rei(fa);rel(cost);
            G[fa].pb(i);
            w[fa].pb(cost);
            G[i].pb(fa);
            w[i].pb(cost);
        }
        dfs(1,-1);
        rep1(i,1,n)
            {
                printf("%I64d",ans[i]-1);
                if (i==n)
                    puts("");
                else
                    putchar(' ');
            }
        return 0;
    }
  • 相关阅读:
    OpenCL多次循环执行内核的一个简单样例
    Visual Studio2013的C语言编译器对C99标准的支持情况
    关于OpenCL中三重循环的执行次序
    jQuery判断复选框是否勾选
    JS动态增加删除UL节点LI
    Javascript玩转继承(三)
    Javascript玩转继承(二)
    Javascript玩转继承(一)
    js方法call和apply实例解析
    简单实用的php分页函数代码
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626813.html
Copyright © 2020-2023  润新知