【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 [解题思路] 这是一个单调队列算法的经典题目,几乎学习单调队列的人都接触过这题. 利用单调队列算法求出每一个固定区间内的最(大/小)值. 以下以最大值为例: ...
随机推荐
- top有用的开关控制命令
[原创]本文为原创博文,转发请注明出处:https://www.cnblogs.com/dingbj/p/top_command.html 今天偶然用到top命令,在动态刷新的界面上输入h顺便看了下帮 ...
- 修改conda和pip源
修改conda源为中科大源 Windows修改C:\Users\user(user替换为当前登陆系统的用户)目录下的.condarc文件 Linux修改家目录下的.condarc文件 channels ...
- egret 解决游戏loading前的黑屏
一.问题 egret游戏loading界面的制作可以参考这个,我就不多赘述啦,步骤也比较详细<Egret制作Loading页面及分步加载资源教程>. 后面我发现即便加上loading,在游 ...
- 使用idea插件识别log文件的相关设置
最近要读一些spring boot项目产生的log文件,众所周知,idea拥有强大的插件系统.当我打开log文件时,idea自动帮我推荐了ideolog这个插件. 但是当我安装好之后发现系统并不能完全 ...
- 24V转3.3V稳压芯片,高效率同步降压DC-DC变换器3A输出电流
PW2312是一个高频,同步,整流,降压,开关模式转换器与内部功率MOSFET.它提供了一个非常紧凑的解决方案,以实现1.5A的峰值输出电流在广泛的输入电源范围内,具有良好的负载和线路调节. PW23 ...
- HTML基础复习1
网页:HTML(超文本标记语言) 网页分为静态网页和动态网页,区别:动态网页中可以加入脚本代码,还可以动态的引入数据库中的信息. HTML的结构 <html> <head>头信 ...
- 02_Python基础
2.1 第一条编程语句 print("Hello, Python!") print("To be, or not to be, it's a question." ...
- uni-app开发经验分享三: Vuex实现登录和用户信息留存
在做用户登录的过程中,其实最重要的是登录成功后的数据要怎么储存,储存到哪里,这里我分享一个利用vuex来实现用户登录和用户数据留存的方法 vuex代码如下: //引入vue和vuex import V ...
- Eureka详解系列(二)--如何使用Eureka(原生API,无Spring)
简介 通过上一篇博客 Eureka详解系列(一)--先谈谈负载均衡器 ,我们知道了 Eureka 是什么以及为什么要使用它,今天,我们开始研究如何使用 Eureka. 在此之前,先说明一点.网上几乎所 ...
- centralized collectors 中心化 采集器
Fluent Bit https://fluentbit.io/ FluentBit is an open source specialized data collector. It provides ...