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的更多相关文章

  1. 【Luogu P2515】软件安装

    Luogu P2515 这道题的题面与P2146有点像.一些不同地方就是P2146是无环的,这题是有环的. 很显然,如果有几个软件的依赖关系形成环,那么这几个软件就可以被看成是一个大软件,其价值和空间 ...

  2. 【Luogu 3275】[SCOI2011]糖果

    Luogu P3275 显然是一道经典的差分约束系统 相关知识可以查看:[Luogu 1993]差分约束系统问题--小K的农场 值得注意的是这题使用最长路更合适,因为每一个人都要取得至少一个糖果.在添 ...

  3. 【Luogu P3388】割点模板

    Luogu P3388 在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合. 如果某个割点集合只含有一个顶点X(也即{X ...

  4. 【Luogu P1164】小A点菜

    题目原链接: Luogu 小A点菜 [解题思路] 常规的0-1背包,不过是求装满整个背包的方案数,只要把0-1背包的状态转移方程稍微改一下就行.因为要求方案数,那么把方程中的max换成sum就行. [ ...

  5. 【30.36%】【codeforces 740D】Alyona and a tree

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  6. 【Luogu P1981】表达式求值

    点我进入原题Luogu P1981 [解题思路] 仔细分析题目,这就是一道模拟题…… 直接按照符号读入全部的数字,先算乘法,最后把全部数加起来就是结果了 记得要%10000取最后四位 [参考程序] # ...

  7. 【Luogu P2563】【集训Day 4 动态规划】质数和分解

    题目链接:Luogu P2563 质数和分解(prime) [问题描述] 任何大于 1 的自然数 N,都可以写成若干个大于等于2且小于等于 N 的质数之和表达式(包括只有一个数构成的和表达式的情况), ...

  8. 【Luogu P1090】合并果子

    Luogu P1090 [解题思路] 刚看到这题的时候,第一反应就是每次取两个最小,然后重新排序,再取最小.但是这样会TLE. 既然找最小的,那就可以利用单调队列了.显然输入的数据是不具有单调性的,但 ...

  9. 【POJ 2823】【Luogu P1886】Sliding Window 滑动窗口

    POJ 2823 Luogu P1886 [解题思路] 这是一个单调队列算法的经典题目,几乎学习单调队列的人都接触过这题. 利用单调队列算法求出每一个固定区间内的最(大/小)值. 以下以最大值为例: ...

随机推荐

  1. Pycharm同时执行多个脚本文件

    Pycharm同时执行多个脚本文件 设置Pycharm使它可以同时执行多个程序 打开Pycharm 找到Run,点击确认 点击Edit Configurations 右上角Allow parallel ...

  2. kubernets与API服务器进行交互

    一  为何需要与kubernets集群的API服务器进行交互 1.1  kubernets提供了一种downapi的资源可以将pod的元数据渲染成环境变量或者downward卷的形式挂载到容器的文件系 ...

  3. C语言变量

    C语言变量 任何一种编程语言都离不开变量,特别是数据处理型程序,变量的使用非常频繁,没有变量参与程序甚至无法编制,即使编制运行后的意义也不大.变量之所以重要,是因为变量是编程语言中数据的符号标识和载体 ...

  4. 检查Mysql主从状态

    .检查MySQL主从同步状态 #!/bin/bash USER=bak PASSWD=123456 IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e  show s ...

  5. 使用fdopen对python进程产生的文件进行权限最小化配置

    需求背景 用python进行文件的创建和读写操作时,我们很少关注所创建的文件的权限配置.对于一些安全性较高的系统,如果我们创建的文件权限其他用户或者同一用户组里的其他用户有可读权限的话,有可能导致不必 ...

  6. 06. struts2中指定struts2处理的请求后缀

    概述 默认情况下我们都是使用.action后缀访问Action. 其实默认后缀是可以通过常量"struts.action.extension"进行修改的. 我们可以配置Struts ...

  7. JavaScript小案例-阶乘!

    JavaScript小案例-阶乘! 阶乘:就是像台阶一样一阶一阶的,从高阶到低阶,依次乘下来!代码超少!容易理解! // factorial 阶乘 // 如果 function factorial(n ...

  8. CODING 再携手腾讯云 Serverless,让开发者跑步上云

    近年来,腾讯云持续在云原生领域打磨和完善产品矩阵,致力于为开发者上云提供更好的产品和服务.继前段时间 CODING CI 助力腾讯云 Serverless 全新应用控制台.持续保障 Serverles ...

  9. ArchLinux安装后所需要的环境和工具

    ArchLinux安装后所需要的环境和工具 工具: Dolphin 文件管理器 ntfs-3G 移动硬盘挂载 octopi 实时检查更新 KDE Connect 手机电脑远程连接 DBeaver Co ...

  10. 标准PE头属性说明