【luogu AT3957】[AGC023F] 01 on Tree
01 on Tree
题目链接:luogu AT3957
题目大意
有一棵根为 \(1\) 的树,每个节点有个值 \(0\) 或 \(1\)。
然后每次你可以把一个没有父亲的点删除,然后把值放进一个数组里。
要你得出的数组逆序对尽可能少,要输出这个最小的逆序对个数。
思路
那我们会发现从根节点开始删会很麻烦,很难处理,那我们考虑反着来:从叶节点开始不断合并,向根节点上传答案。
那我们要先发现一件事,对于一个点 \(x\) 的一个子树 \(y\),它不管 \(y\) 里面怎么排列,里面产生了多少个逆序对,最终排列 \(x\) 里面的每个子树的时候,看的只是 \(y\) 里面有多少个 \(0\),多少个 \(1\),是不会管里面怎么排列的。
那我们就可以对于每个子树都看它怎么排列好。我们贪心一下。
首先,对于两个子树 \(i,j\),设它们 \(0\) 的数量为 \(num0_i,num0_j\),\(1\) 的数量为 \(num1_i,num1_j\)。
那如果 \(i\) 在 \(j\) 的前面,新增逆序对的个数就是 \(num1_i\times num0_j\)。如果在后面,就是 \(num1_j\times num0_i\)。
那假设 \(i\) 放前面比 \(j\) 放前面优,那就是 \(num1_i\times num0_j < num1_j\times num0_i\)。
那这个我们可以用堆来维护。
但是这是不能直接递归来搞的,我们要把每个点都看成独立,然后想父亲的方向合并。
那其实 \(num0,num1\) 记录的其实变成了这个点所在的连通块的 \(0,1\) 个数。
那显然上面的贪心在这里还是可以的。
那我们要维护 \(0,1\) 个数,自然要用并查集。
记得要判断当前点是否被删掉,因为当合并完之后,它父亲节点要删去,我们只要看 \(num0,num1\),就可以得知是否被合并。
还有一点就是 \(1\),也就是根节点是不用再合并的,因为没有父亲。
代码
#include<queue>
#include<cstdio>
using namespace std;
struct Teap {
int x, num_1, num_0;
};
bool operator < (Teap x, Teap y) {//用堆将点按贪心思想排序
return 1ll * x.num_0 * y.num_1 < 1ll * x.num_1 * y.num_0;
}
int n, a[200001], father[200001];
int fa[200001], num[200001][2];
long long ans;
priority_queue <Teap> q;
int find(int now) {//并查集
if (father[now] == now) return now;
return father[now] = find(father[now]);
}
int main() {
scanf("%d", &n);
for (int i = 2; i <= n; i++) {
scanf("%d", &fa[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
num[i][a[i]]++;
father[i] = i;
}
for (int i = 2; i <= n; i++)
q.push((Teap){i, num[i][1], num[i][0]});
while (!q.empty()) {
Teap now = q.top();
q.pop();
int x = find(now.x);
if (num[x][0] != now.num_0 || num[x][1] != now.num_1)
continue;//这个点已近被删除
int y = find(fa[x]);
ans += 1ll * num[x][0] * num[y][1];//加上逆序对个数
num[y][0] += num[x][0];//这个子树所包含的0/1的个数增加
num[y][1] += num[x][1];
father[x] = y;//并查集连接
if (y != 1)//继续下去
q.push((Teap){y, num[y][1], num[y][0]});
}
printf("%lld", ans);
return 0;
}
【luogu AT3957】[AGC023F] 01 on Tree的更多相关文章
- 【Luogu P2515】软件安装
Luogu P2515 这道题的题面与P2146有点像.一些不同地方就是P2146是无环的,这题是有环的. 很显然,如果有几个软件的依赖关系形成环,那么这几个软件就可以被看成是一个大软件,其价值和空间 ...
- 【Luogu 3275】[SCOI2011]糖果
Luogu P3275 显然是一道经典的差分约束系统 相关知识可以查看:[Luogu 1993]差分约束系统问题--小K的农场 值得注意的是这题使用最长路更合适,因为每一个人都要取得至少一个糖果.在添 ...
- 【Luogu P3388】割点模板
Luogu P3388 在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合. 如果某个割点集合只含有一个顶点X(也即{X ...
- 【Luogu P1164】小A点菜
题目原链接: Luogu 小A点菜 [解题思路] 常规的0-1背包,不过是求装满整个背包的方案数,只要把0-1背包的状态转移方程稍微改一下就行.因为要求方案数,那么把方程中的max换成sum就行. [ ...
- 【30.36%】【codeforces 740D】Alyona and a tree
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【Luogu P1981】表达式求值
点我进入原题Luogu P1981 [解题思路] 仔细分析题目,这就是一道模拟题…… 直接按照符号读入全部的数字,先算乘法,最后把全部数加起来就是结果了 记得要%10000取最后四位 [参考程序] # ...
- 【Luogu P2563】【集训Day 4 动态规划】质数和分解
题目链接:Luogu P2563 质数和分解(prime) [问题描述] 任何大于 1 的自然数 N,都可以写成若干个大于等于2且小于等于 N 的质数之和表达式(包括只有一个数构成的和表达式的情况), ...
- 【Luogu P1090】合并果子
Luogu P1090 [解题思路] 刚看到这题的时候,第一反应就是每次取两个最小,然后重新排序,再取最小.但是这样会TLE. 既然找最小的,那就可以利用单调队列了.显然输入的数据是不具有单调性的,但 ...
- 【POJ 2823】【Luogu P1886】Sliding Window 滑动窗口
POJ 2823 Luogu P1886 [解题思路] 这是一个单调队列算法的经典题目,几乎学习单调队列的人都接触过这题. 利用单调队列算法求出每一个固定区间内的最(大/小)值. 以下以最大值为例: ...
随机推荐
- 使用K8s的一些经验和体会
坑 Java应用程序的奇怪案例 在微服务和容器化方面,工程师倾向于避免使用 Java,这主要是由于 Java 臭名昭著的内存管理.但是,现在情况发生了改变,过去几年来 Java 的容器兼容性得到了 ...
- C/C++内存对齐详解
1.什么是内存对齐 还是用一个例子带出这个问题,看下面的小程序,理论上,32位系统下,int占4byte,char占一个byte,那么将它们放到一个结构体中应该占4+1=5byte:但是实际上,通过运 ...
- SpringBoot Logback无法获取配置中心属性
SpringBoot Logback无法获取配置中心属性 前言 最近在做项目中,需要把项目中的日志信息通过RabbitMQ将规定格式的消息发送到消息队列中,然后ELK系统通过消息队列拿日志并且保存起来 ...
- Python机器学习笔记:奇异值分解(SVD)算法
完整代码及其数据,请移步小编的GitHub 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/MachineLearningNote 奇异值分解(Singu ...
- ctfhub技能树—文件上传—MIME绕过
什么是MIME MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型.是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访 ...
- Linux下安装配置rocketmq (单个Master、双Master)
一.环境: centos7(2台虚拟机):192.168.64.123:192.168.64.125 apache-maven-3.2.5(官网要求maven版本是3.2.x,版本不同,编译rocke ...
- RocketMQ在linx安装及其有关问题解决
Linx安装和使用: rocketmq官网:http://rocketmq.apache.org/ 首先安装JDK(推荐使用JDK1.8),并配置环境变量 下载rocketmq压碎包并解压到指定目录 ...
- FPGA仿真的概念及语法特点
以下是特权同学<FPGA设计+实战演练>书中的描述: 一个正规的设计需要花费在验证上的工作量,往往可能会占到整个开发流程的70%左右.验证通常分为仿真验证和板机验证. ...
- 试玩 GOWOG ,初探 OpenAI(使用 NeuroEvolution 神经进化)与 Golang 多人在线游戏开发
GOWOG: 原项目:https://github.com/giongto35/gowog 我调整过的:https://github.com/Kirk-Wang/gowog GOWOG 是一款迷你的, ...
- 多路复用器Select、Poll、Epoll区别梳理
注意:本文是本人的学习总结,可能存在理解上的错误,请带着怀疑眼光看待,如果有不准确的地方欢迎指出,疑义相与析.为了叙述完整性,前面有一些前置知识,可以根据目录直接看后面的详解部分. 前置知识 用户态与 ...