【LG4437】[HNOI/AHOI2018]排列
【LG4437】[HNOI/AHOI2018]排列
题面
题解
题面里这个毒瘤的东西我们转化一下:
对于\(\forall k,j\),若\(p_k=a_{p_j}\),则\(k<j\)。
也就是说若\(y=a_x\),则\(y\)排在\(x\)前面,
那么我们在原数组编号中\(a_x\)向\(x\)连边可以表示出这种拓扑关系。
那么我们连玩边后肯定是以\(0\)为根的一颗有根树,否则一定会形成一个环,无解。
贪心地想一下,对于权值最小的点,我们肯定让它尽量往前选,那么在它父亲选完后,我们一定会选它,所以我们可以考虑把它的权值并到它父亲上。
这样子的话,我们每个点就变成了一个序列,
考虑两个序列\(a,b\)的合并方式决定最优答案(当前已经到了第\(i\)位):
W_{ba}=\sum_{j=1}^{m_2}(i+j)w_{b_j}+\sum_{j=1}^{m_1}(i+j+m_2)w_{a_j}\\
W_{ab}-W_{ba}=m_1W_b-m_2W_a
\]
那么如果\(W_{ab}>W_{ba}\)则\(\frac{W_a}{m_1}<\frac{W_b}{m_2}\),也就是平均数小的放前面。
具体实现详见代码。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 5e5 + 5;
struct Graph { int next, to; } e[MAX_N << 1]; int fir[MAX_N], e_cnt;
void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; }
void Add_Edge(int u, int v) { e[e_cnt] = (Graph){fir[u], v}; fir[u] = e_cnt++; }
bool vis[MAX_N];
int N, tot, pa[MAX_N], fa[MAX_N], size[MAX_N];
long long w[MAX_N];
void dfs(int x) {
vis[x] = 1, ++tot;
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to;
if (vis[v]) { puts("-1"); exit(0); }
else dfs(v);
}
}
int getf(int x) { return pa[x] == x ? x : pa[x] = getf(pa[x]); }
struct Node { int u, sz; long long w; } ;
bool operator < (const Node &l, const Node &r) { return l.w * r.sz > r.w * l.sz; }
struct Heap{
Node h[MAX_N]; int cur;
Node top() { return h[1]; }
void push(const Node &x) { h[++cur] = x; push_heap(&h[1], &h[cur + 1]); }
void pop() { pop_heap(&h[1], &h[cur + 1]); --cur; }
bool empty() { return cur == 0; }
} que;
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
clearGraph();
N = gi();
for (int i = 1; i <= N; i++) fa[i] = gi(), Add_Edge(fa[i], i);
for (int i = 1; i <= N; i++) w[i] = gi();
dfs(0); if (tot <= N) return puts("-1") & 0;
for (int i = 0; i <= N; i++) pa[i] = i, size[i] = 1;
for (int i = 1; i <= N; i++) que.push((Node){i, 1, w[i]});
long long ans = 0;
while (!que.empty()) {
Node p = que.top(); que.pop();
int u = getf(p.u);
if (size[u] != p.sz) continue;
int f = getf(fa[u]); pa[u] = f;
ans += w[u] * size[f], w[f] += w[u], size[f] += size[u];
if (f) que.push((Node){f, size[f], w[f]});
}
printf("%lld\n", ans);
return 0;
}
【LG4437】[HNOI/AHOI2018]排列的更多相关文章
- [HNOI/AHOI2018]排列 贪心
题面 题解: 把题面的限制换成中文: 如果排在第k位的下标 = 排在第j位的值 ,那么k < j 换一个描述方式: 一个值为x的数要排在第x个数后面. 再换一个描述方式: \(fa[i] = a ...
- [HNOI/AHOI2018]排列
[Luogu4437] 如果\(a[i]=j\)则序列\(p[]\)中\(j\)必须排在\(i\)前面,如果\(j\)不在范围内则不管,求一个式子\(\sum_{i=1}^n iw_{p[i]}\)的 ...
- 洛谷 P4437 [HNOI/AHOI2018]排列(贪心+堆,思维题)
题面传送门 开始 WA ycx 的遗产(bushi 首先可以将题目转化为图论模型:\(\forall i\) 连边 \(a_i\to i\),然后求图的一个拓扑序 \(b_1,b_2,\dots b_ ...
- BZOJ5289 HNOI/AHOI2018排列(贪心+堆)
题面描述的相当绕,其实就是如果ai=j,重排后ai要在aj之后.同时每个ai有附属属性wi,要求最大化重排后的Σiwi. 容易发现这事实上构成一张图,即由j向i连边.由于每个点入度为1或0,该图是基环 ...
- 【洛谷 P4437】 [HNOI/AHOI2018]排列(贪心,堆)
题目链接 如果\(j<=k,a_{p[j]}!=p[k]\)可以理解为如果\(a_{p[j]}=p[k]\),那么\(k\)一定要放在\(j\)前面,也就是\(a_j\)在\(j\)前面. 于是 ...
- BZOJ5289 & 洛谷4437:[HNOI/AHOI2018]排列——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5289 https://www.luogu.org/problemnew/show/P4437 考虑 ...
- Poj2054 color a tree && [HNOI/AHOI2018]排列
https://zybuluo.com/ysner/note/1120723 题面 原题 某省选强化题 大致意思是给你一颗树,选父亲后才能选儿子. 每个点对答案的贡献为你在第几次选这个点 × 该点权值 ...
- luogu P4437 [HNOI/AHOI2018]排列
luogu 问题本质是把\(a_i\)作为\(i\)的父亲,然后如果有环就不合法,否则每次要取数,要满足取之前他的父亲都被取过(父亲为0可以直接取),求最大价值 贪心想法显然是要把权值大的尽量放在后面 ...
- 【题解】Luogu P4436 [HNOI/AHOI2018]游戏
原题传送门 \(n^2\)过百万在HNOI/AHOI2018中真的成功了qwqwq 先将没门分格的地方连起来,枚举每一个块,看向左向右最多能走多远,最坏复杂度\(O(n^2)\),但出题人竟然没卡(建 ...
随机推荐
- (三十七)golang--如何获取命令行参数
1.第一种方式 缺点:参数的接收受输入的顺序所影响. 2.第二种方式(使用flag包)
- 【shell脚本】通过位置变量创建Linux账户及密码===addUser.sh
通过位置变量创建Linux账户及密码 脚本内容 [root@VM_0_10_centos shellScript]# vi addUser.sh #!/bin/bash # 通过位置变量创建系统账户及 ...
- 你需要知道的8个CSS带@的规则
1:@charset(用来设置html文档字符编码的格式,比如我们常用的,charset='utf-8') 注:建议CSS文件最顶部都加上@charset "utf-8";,避免出 ...
- vuex 源码解析(四) mutation 详解
mutation是更改Vuex的store中的状态的唯一方法,mutation类似于事件注册,每个mutation都可以带两个参数,如下: state ;当前命名空间对应的state payload ...
- RootKit随手记(一)RootKit的驱动隐藏、读取配置、卸载安装
边学习边更新这专题,随手记录一下用到的思路,给自己看的(所以读者看可能有些懵,不好意思...) RootKit随手记(一)RootKit的驱动隐藏.读取配置.卸载安装 一.驱动隐藏 1. 隐藏原理 一 ...
- Spring-AOP源码分析随手记(二)
这次来分析下切面的执行过程. 1.怎么看? 怎么开始看源码呢?就直接从被增强的方法调用那里打断点,看看怎么执行的: 然后就来到了这: 2.初步分析 里面有段: if (this.advised.exp ...
- Prism——Window 必须是树的根目录。不能将 Window 添加为 Visual 的子目录。
这个错误就是作为Region的view添加时选成了界面,正确的应在添加时选择用户控件. 解决方法: 这俩处的Window改为UserControl即可.
- element-ui Upload 上传组件源码分析整理笔记(十四)
简单写了部分注释,upload-dragger.vue(拖拽上传时显示此组件).upload-list.vue(已上传文件列表)源码暂未添加多少注释,等有空再补充,先记下来... index.vue ...
- 【AI测试】也许这有你想知道的人工智能 (AI) 测试--第二篇
概述此为人工智能 (AI) 测试第二篇 第一篇主要介绍了 人工智能测试.测试什么.测试数据等.第二篇主要介绍测试用例和测试报告.之后的文章可能具体介绍如何开展各项测试,以及具体项目举例如何测试.测试用 ...
- Scrum冲刺第三篇
一.每日例会 会议照片 成员 昨日已完成的工作 今日计划完成的工作 工作中遇到的困难 陈嘉欣 撰写博客,管理成员提交代码 每日博客,根据队员代码问题更改规范文档安排后续工作 队员提交的代码管理困难 邓 ...