• 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;
    }
    
  • 相关阅读:
    Dubbo探索(七)
    Dubbo探索(六)
    Dubbo探索(五)
    Dubbo探索(四)
    Redis主节点内存占用过高
    修改RedHat 7.2 进程最大句柄数限制
    Linux 数据分析常用 shell命令
    流处理
    根域名服务器
    并发与并行(concurrency vs parallesim)
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14117156.html
Copyright © 2020-2023  润新知