5289: [Hnoi2018]排列
5289: [Hnoi2018]排列
分析:
首先将题意转化一下:每个点向a[i]连一条边,构成了一个以0为根节点的树,要求选一个拓扑序,点x是拓扑序中的第i个,那么价值是i*w[x]。让价值最大。
然后贪心:直观的考虑,应该让权值小的尽量靠前,那么依次考虑当前最小的权值,一旦选了它的父节点,那么下一个就会选它。将它和父节点合并,新的权值为平均数,并且记录下siz。推广一下即每次选平均数最小的集合,和父节点所在的集合合并。
证明:如果当前有两个集合x,y,如果x在前面更优,那么$w[x] + w[y] \times siz[x] > w[y] + w[x] \times siz[y]$
$w[x] \times (siz[y] - 1) < w[y] \times (siz[x] - 1 ) $
$\frac{w[x]}{siz[x] - 1} < \frac{w[y]}{siz[y] - 1}$
所以x在y前面的条件是平均数小,那么就可以用堆来维护了。注意一下如果平均数比较的话,要开long double,或者直接按照上面的第二个式子来比较,不存在精度问题。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} #define pa pair<long double,int>
const int N = ;
int fa[N], a[N], siz[N];
LL w[N]; struct Heap{
priority_queue< pa, vector< pa >, greater< pa > > a, b;
void Insert(pa x) { a.push(x); }
void Delete(pa x) { b.push(x); }
pa Top() {
while (!b.empty() && a.top() == b.top()) a.pop(), b.pop();
return a.top();
}
}q;
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
int main() {
int n = read();
for (int i = ; i <= n; ++i) fa[i] = i;
for (int i = ; i <= n; ++i) {
a[i] = read();
int u = find(a[i]), v = find(i);
if (u != v) fa[u] = v;
else { puts("-1"); return ; }
}
LL ans = ;
for (int i = ; i <= n; ++i) fa[i] = i;
for (int i = ; i <= n; ++i) {
w[i] = read(); siz[i] = ; ans += w[i];
q.Insert(pa(w[i], i));
}
for (int k = ; k <= n; ++k) {
pa now = q.Top(); q.Delete(now);
int x = now.second, y = find(a[x]);
if (y) q.Delete(pa((long double)w[y] / siz[y], y));
ans += 1ll * siz[y] * w[x];
w[y] += w[x]; siz[y] += siz[x]; fa[x] = y;
if (y) q.Insert(pa((long double)w[y] / siz[y], y));
}
cout << ans;
return ;
}
5289: [Hnoi2018]排列的更多相关文章
- bzoj 5289: [Hnoi2018]排列
Description Solution 首先注意到实际上约束关系构成了一棵树 考虑这个排列 \(p\),编号为 \(a[i]\) 的出现了,\(i\) 才可以出现 那么如果连边 \((a[i],i) ...
- 【BZOJ5289】[HNOI2018]排列(贪心)
[BZOJ5289][HNOI2018]排列(贪心) 题面 BZOJ 洛谷 题解 这个限制看起来不知道在干什么,其实就是找到所有排列\(p\)中,\(p_k=x\),那么\(k<j\),其中\( ...
- BZOJ.5289.[AHOI/HNOI2018]排列(贪心 heap)
BZOJ LOJ 洛谷 \(Kelin\)写的挺清楚的... 要求如果\(a_{p_j}=p_k\),\(k\lt j\),可以理解为\(k\)要在\(j\)之前选. 那么对于给定的\(a_j=k\) ...
- [HNOI2018]排列
Description: 给定 \(n\) 个整数 \(a_1, a_2, \dots, a_n, 0 \le a_i \le n\),以及 \(n\) 个整数 \(w_1, w_2, \dots, ...
- [HNOI2018]排列[堆]
题意 给定一棵树,每个点有点权,第 \(i\) 个点被删除的代价为 \(w_{p[i]}\times i\) ,问最小代价是多少. 分析 与国王游戏一题类似. 容易发现权值最小的点在其父亲选择后就会立 ...
- BZOJ5289: [Hnoi2018]排列
传送门 第一步转化,令 \(q[p[i]]=i\),那么题目变成: 有一些 \(q[a[i]]<q[i]\) 的限制,\(q\) 必须为排列,求 \(max(\sum_{i=1}^{n}w[i] ...
- BZOJ5289:[HNOI2018]排列
我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...
- loj2509 hnoi2018排列
题意:对于a数组,求它的一个合法排列的最大权值.合法排列:对于任意j,k,如果a[p[j]]=p[k],那么k<j. 权值:sigma(a[p[i]]*i).n<=50W. 标程: #in ...
- 【比赛】HNOI2018 排列
这题原题... 这题题面七绕八绕,有点麻烦,反正最后转化就是一棵树,每个点有一个值,要把所有点选完,要求选择一个点必须是它的父亲和祖先已经全部被选了,贡献是这个点的权值乘上它被选择的排名 如果一个点是 ...
随机推荐
- .net 和 core 数据库连接字符串
Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-xxxx.mdf;Initial Catalog= ...
- pathlib
导入Path类 from pathlib import Path 创建Path对象 p = Path('C:\Windows\System32') # 用C:\Windows\System32创建Pa ...
- HDU1407 测试你是否和LTC水平一样高
题目大意:给出一个num,计算方程x^2+y^2+z^2 = num的第一个正整数解(字典序),0 < num <= 10000. 方法参考了网上的博客,自己打了一波,发现还有很多不懂的地 ...
- 多线程操作C++ STL vector出现概率coredump问题及尽量避免锁的双缓冲队列
多线程操作全局变量,必须考虑同步问题,否则可能出现数据不一致, 甚至触发coredump. 前段时间, 遇到一个多线程操作了全局的vector的问题, 程序崩了.场景是这样的:某全局配置参数保存在一 ...
- 扯不清楚的virtual和abstract
定义Person类: class Person { public void Say() { Console.WriteLine("I am a person"); } } 现在,我 ...
- 1015. [JSOI2008]星球大战【并查集】
Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的 机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通 ...
- 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家
[题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...
- sql按月模糊查询
select * from tb where convert(varchar(7),date,120) = '2011-05'
- 9、Android---UI---Material Design
9.1.什么是Material Design 由谷歌的设计师基于传统优秀设计原则,结合丰富的创意和科学技术所发明的一套全新的界面设计语言 包含了视觉.运行.互动等效果 Material Design的 ...
- 程序集(Assembly)和模块(Managed Module)
前言 一直都用集成开发坏境(IDE),一直对模块和程序集的概念理解的不是很直观,因为一Build就把你的单个模块塞进程序集里面去了.当然,对你的编程也不会造成太大的影响.但有些东西你最好还是知道比较好 ...