zoukankan      html  css  js  c++  java
  • cf1388D Captain Flint and Treasure

    传送门
    给出两个数组(a,b),需要对每一个(i)进行操作,(ans += a[i]),如果说(b_i ≠ -1),那么就把(a[b[i]] += a[i])
    求出(ans)和操作的下标情况

    首先分析一下如果对于所有的(b[i]≠-1)的情况,如果(a[b[i]])加上了(a[i]),那么(a[b[b[i]]])可能也要加上(a[i]),也就是说存在累加性。那么就是说对于所有的(a[i]≥0 and b[i]≠-1)的情况,我们就考虑最优累加,(b[i])小的放前面,(b[i])大的放后面,就能实现累加了。

    而对于(a[i] < 0 and b[i] ≠ -1)的情况,相当于按照(b[i])去从大到小存,防止累加的情况

    但是不能简单的用vector去存放,因为(a[i])的值其实是动态更新的,所有建立一个拓扑排序,如果说存在(bb[i] ≠ -1)的情况,那么久在(i)(b[i])连一条有向边,然后跑一下拓扑排序。

    对于有优先级顺序,且对后面值具有累加性的情况下,可以考虑下拓扑排序

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    const int N = 2e5 + 5;
    ll a[N];
    int b[N], in[N], n;
    struct Edge{
        int to, next;
    }e[N << 1];
    int head[N], tot;
    void add(int u, int v){
        e[++tot].to = v;
        e[tot].next = head[u];
        head[u] = tot;
    }
    void topu(){
        queue <int> q;//小顶堆
        for(int i = 1; i <= n; i++){
            if(!in[i]) q.push(i);
        }
        std::vector<int> ans;
        ll res = 0;
        stack<int> ss;
        while(!q.empty()){
            int u = q.front();
            q.pop();
            if(a[u] >= 0) ans.push_back(u), res += a[u];
            else ss.push(u);
            for(int i = head[u]; i; i = e[i].next){
                int v = e[i].to;
                if(a[u] >= 0) a[v] += a[u];
                in[v]--;
                if(!in[v]) q.push(v);
            }
        }
        while(!ss.empty()){
            int now = ss.top();
            ss.pop();
            res += a[now];
            ans.push_back(now);
        }
        printf("%lld
    ", res);
        for(int i = 0; i < ans.size(); i++)
            printf("%d%c", ans[i], " 
    "[i == ans.size() - 1]);
    }
    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
        for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
        for(int i = 1; i <= n; i++) {
            if(b[i] != -1) {
                add(i, b[i]);
                in[b[i]]++;
            }
        }
        topu();
        return 0;
    }
    
  • 相关阅读:
    Hdu 5396 Expression (区间Dp)
    Lightoj 1174
    codeforces 570 D. Tree Requests (dfs)
    codeforces 570 E. Pig and Palindromes (DP)
    Hdu 5385 The path
    Hdu 5384 Danganronpa (AC自动机模板)
    Hdu 5372 Segment Game (树状数组)
    Hdu 5379 Mahjong tree (dfs + 组合数)
    Hdu 5371 Hotaru's problem (manacher+枚举)
    Face The Right Way---hdu3276(开关问题)
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14117156.html
Copyright © 2011-2022 走看看