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;
    }
    
  • 相关阅读:
    创建型模式
    创建、修改、删除表总结
    分页式存储管理及地址转换(网易笔试题)
    二进制、十进制、十六进制相互转换
    转 String,StringBuffer与StringBuilder的区别??
    IDEA 修改某个Module名称
    IDEA Git 修改后的文件无法Commit
    git git push某一次的commit记录
    git merge 结果是 git merge Already up-to-date. 该怎么解决?
    火币网API文档——REST 行情、交易API简介
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14117156.html
Copyright © 2011-2022 走看看