zoukankan      html  css  js  c++  java
  • 【洛谷 P4437】 [HNOI/AHOI2018]排列(贪心,堆)

    题目链接
    如果(j<=k,a_{p[j]}!=p[k])可以理解为如果(a_{p[j]}=p[k]),那么(k)一定要放在(j)前面,也就是(a_j)(j)前面。
    于是连边((a[j],j)),表示(a[j])(j)前面,如果有环就是无解,如果没有环那么一定是一棵以(0)为根的树
    根据题意,我们肯定是要尽量把(w)小的安排在前面。
    于是考虑这样一个贪心:
    对于当前最小(w_i)
    如果(fa[i]=0),那么肯定直接选(i)
    如果(fa[i]!=0),那么当选完(fa[i])后肯定马上选(i)
    于是就可以把(fa[i])(i)合并了。
    合并了以后显然不能按权值和排序,而要按权值的平均值。
    维护当前最小可以用堆,
    但合并后要修改权值,可以用平板电视的带修改堆,或者标记一下有没有被合并。
    统计答案类似秦九韶定理。

    #include <cstdio>
    #include <queue>
    using namespace std;
    inline int read(){
        int s = 0, w = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); }
        return s * w;
    }
    const int MAXN = 500010;
    struct Edge{
    	int next, to;
    }e[MAXN];
    int head[MAXN], num;
    inline void Add(int from, int to){
    	e[++num].to = to; e[num].next = head[from]; head[from] = num;
    }
    struct node{
    	int size, id;
    	long long val;
    	int operator > (const node A) const{
    		return val * A.size > A.val * size;
    	}
    }now;
    int n, p;
    long long ans;
    int vis[MAXN], f[MAXN], size[MAXN], fa[MAXN];
    long long w[MAXN];
    priority_queue <node, vector<node>, greater<node> > q;
    int dfs(int u){
    	vis[u] = 1;
    	for(int i = head[u]; i; i = e[i].next)
    	   if(vis[e[i].to])
    	     return 1;
    	   else
    	   	 if(dfs(e[i].to)) return 1;
    	return 0;
    }
    int find(int x){
    	return f[x] == x ? x : f[x] = find(f[x]);
    }
    int main(){
    	n = read(); size[0] = 1;
    	for(int i = 1; i <= n; ++i)
    	   Add(fa[i] = read(), f[i] = i);
    	if(!head[0] || dfs(0)){ printf("-1"); return 0; }
    	for(int i = 1; i <= n; ++i){
    	   w[i] = read();
    	   q.push( (node){ size[i] = 1, i, w[i] } );
        }
    	while(q.size()){
    		now = q.top(); q.pop();
    		if(size[now.id] ^ now.size) continue;
    		f[now.id] = p = find(fa[now.id]); ans += w[now.id] * size[p];
    		size[p] += size[now.id]; w[p] += w[now.id];
    		if(p) q.push((node){ size[p], p, w[p] });
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    正则表达式简介
    PHP中简单的页面缓冲技术
    PHP 程序加速探索
    PHP中通过Web执行C/C++应用程序
    PHP实现聊天室的主动更新与被动更新
    php中Cookie及其使用
    Linux 下 PHP 连接 MS SQLServer 的办法
    网站加速 PHP 缓冲的免费实现方法
    Spark Streaming中的基本操作函数实例
    Scala中的s函数
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/10382313.html
Copyright © 2011-2022 走看看