题解:POI2012 Salaries
题解:POI2012 Salaries
Description
The Byteotian Software Corporation (BSC) has \(n\) employees.
In BSC's strict hierarchy, each employee has a direct supervisor, except the CEO, to whom all other BSC employees answer, directly or not.
Each employee has a unique monthly salary, and all their salaries range from 1 to \(n\) bythalers.
Each supervisor earns more than each of their subordinates.
According to Byteotian law, the salaries of employees on certain posts may be publicly disclosed.
Furthermore, if the salary of an employee is disclosed, then the salary of their supervisor is also disclosed.
The Byteotian Internal Revenue Anti-Corruption Service (BIRAS) has decided to investigate BSC.
Before BIRAS enters BSC with a warrant, they intend to learn the salaries of all BSC employees that are not disclosed but can be determined from those that are disclosed.
题意:
给一棵 \(n\) 个结点的树,点权取 \(1 \sim n\) 且 各不相同。
满足任意非根结点的权值一定比它的父节点权值小。
现在自顶向下地已知一些点的权值(即若某非根点权值已知,其父节点的权值也一定已知),
问哪些点的权值能唯一确定。
\(n \leq 1e6\)
Algorithm
这是一道 十分有趣 而 一言难尽 的题目。
我们先从两个例子入手,试图理解一下「唯一确定」的意思。
例一

在这里,由于点 \(b\) 是点 \(3\) 的孙子结点,最大只能取 \(1\) ,因此唯一确定 \(b = 1\)
同时,点 \(a\) 是点 \(3\) 的儿子结点,可能的取值有 \(1, 2\) ,但因为 \(b = 1\) ,所以唯一确定 \(a = 2\)
例二

此处 \(a, b\) 都是 \(3\) 的子节点,他们的取值可能为 \(1, 2\) ,但并不能唯一确定一种对应关系。
\(c\) 是 \(5\) 的子节点,可能的取值有 \(1, 2, 4\) 。但因为 \(a, b\) 对应 \(1, 2\) ,只能有 \(c = 4\) ,这也是唯一确定的。
揆诸上例与题面自顶向下给权的性质,我们容易发现:
对于任意一个未确定的结点,它的可能取值范围总是 \((0,x_i]\) ,
其中, \(x_i\) 是由树的结构与已知点权共同决定的。
一个点的权能被唯一确定,当且仅当其取值范围为 \((x_i - 1, x_i]\)
当我们确定了 \(k\) 个结点的取值后,剩余的未确定结点的取值范围就会变化为 \((k, x_i]\)
确定点权的顺序总是从小到大的。
(写成左开右闭的形式仅仅是为了规避区间左右端点相等的写法,没别的意思)
接下来只要模拟上述的推理即可。
我们可以首先一次 DFS 遍历整棵树,根据树结构维护每个点可能的最大取值。
特别注意此处有个坑,如果仅根据点的祖先结点取值和深度计算 \(x_i\) 的话代码就是错误的。
经过这种方法计算出的值 \(x'_i\) 可能已经被某个已知点取了,你需要尝试不断减少 \(x'_i\) 的值直到其符合定义为止。
这个"不断减少"的过程可以预处理出来。
DFS 之后,我们可以根据最大取值将点排序,再依次考虑每个权是否可以被确定或唯一确定。
这个算法描述起来还挺模糊的……不如直接读代码:
#include<bits/stdc++.h>
using namespace std;
template<class T>
inline void read(T &x)
{
char c = getchar(); x = 0;
while(c < '0' || '9' < c) c = getchar();
while('0' <= c && c <= '9')
{
x = (x << 1) + (x << 3) + c - 48;
c = getchar();
}
}
const int INF = 0x7f7f7f7f;
typedef pair<int, int> Node;
vector<Node> ord;
template<const int N, const int M>
class Tree {
private:
int beg[N], nex[M], tar[M], len;
public:
int vap[N], van[N];
bool vis[N];
Tree():len(1) {}
inline void add_egde(int a, int b)
{
++len, tar[len] = b;
nex[len] = beg[a], beg[a] = len;
}
void dfs(int cur, int val)
{
if(!vap[cur]) ord.push_back(Node(val, cur));
for(int i = beg[cur]; i; i = nex[i])
{
if(vap[tar[i]]) dfs(tar[i], vap[tar[i]]);
else dfs(tar[i], van[val - 1]);
}
}
};
Tree<1048576, 1048576> T;
int main()
{
int n, rot;
read(n);
for(int i = 1, x; i <= n; ++i)
{
read(x), read(T.vap[i]);
if(x == i) rot = i, T.vap[i] = n;
else T.add_egde(x, i);
if(T.vap[i])
T.vis[T.vap[i]] = true;
}
for(int i = 1; i <= n; ++i)
{
if(T.vis[i]) T.van[i] = T.van[i - 1];
else T.van[i] = i;
}
T.dfs(rot, n);
sort(ord.begin(), ord.end());
int done = 0, len = ord.size();
for(int i = 1, j = 0; i <= n; i++)
{
if(T.vis[i]) done++;
else
{
int cnt = 0;
while(j < len && ord[j].first == i) j++, cnt++;
if(cnt == 1 && done == i - 1)
T.vap[ord[j - 1].second] = i;
done += cnt;
}
}
for(int i = 1; i <= n; ++i)
printf("%d\n", T.vap[i]);
return 0;
}
题解:POI2012 Salaries的更多相关文章
- 【BZOJ2799】[Poi2012]Salaries 乱搞
[BZOJ2799][Poi2012]Salaries Description 给出一棵n个结点的有根树,结点用正整数1~n编号.每个结点有一个1~n的正整数权值,不同结点的权值不相同,并且一个结点的 ...
- [BZOJ2799][Poi2012]Salaries
2799: [Poi2012]Salaries Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 91 Solved: 54[Submit][Statu ...
- [POI2012]Salaries
题目大意: 给定一棵n带权树,每个点的权值在[1,n]范围内且互不相等,并满足子结点的权值一定小于父结点. 现在已知一个包含根结点的联通块中个点的权值,求剩下哪些点的权值能够被求出,并求出这些权值. ...
- bzoj 2799 [Poi2012]Salaries 性质+二分
题目大意 给出一棵n个结点的有根树,结点用正整数1~n编号. 每个结点有一个1~n的正整数权值,不同结点的权值不相同, 并且一个结点的权值一定比它父结点的权值小(根结点的权值最大,一定是n). 现在有 ...
- POI2012题解
POI2012题解 这次的完整的\(17\)道题哟. [BZOJ2788][Poi2012]Festival 很显然可以差分约束建图.这里问的是变量最多有多少种不同的取值. 我们知道,在同一个强连通分 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- [Poi2012]Festival 题解
[Poi2012]Festival 时间限制: 1 Sec 内存限制: 64 MB 题目描述 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: 1. 给出a,b (1 ...
- 【题解】 [POI2012]FES-Festival (差分约束)
懒得复制题面,戳我戳我 Question: (因为网上找不到好的翻译,这里简单复述一下) 告诉你\(m1+m2\)个约束条件,然后要你找出\(X_1-X_n\)这些数字,求满足要求的数列中不同的数字个 ...
- BZOJ2802: [Poi2012]Warehouse Store
2802: [Poi2012]Warehouse Store Time Limit: 10 Sec Memory Limit: 64 MBSec Special JudgeSubmit: 121 ...
随机推荐
- logback1.11的一个bug:有线程持续不断写入log文件,log文件就不会按设定以日期切换。
此Bug的解决方案请见:https://www.cnblogs.com/xiandedanteng/p/12205422.html logback是log4j的后继者,作者也是同一人,但其中的bug不 ...
- linux基础一(目录结构)
一.linux目录结构 1.根目录/下 bin:用户二进制文件,常用命令都在此目录下 sbin;这个目录下的linux命令通常由系统管理员使用 etc:包含所有程序所需的配置文件,以及服务的启动文件 ...
- oracle之三手工不完全恢复
手工不完全恢复 4.1 不完全恢复的特点: 1)让整个database 回到过去某个时间点,不能避免数据丢失. 2)想跳过坏日志而继续恢复所有其他工作是不可能的,前滚没有这个功能(考点). 3)必须以 ...
- JDK的安装与环境变量的配置
一.JDK的安装 1. JDK的下载地址 https://www.oracle.com/java/technologies/javase-downloads.html. 2. 当前最流行的是 ...
- Golang的Context介绍及其源码分析
简介 在Go服务中,对于每个请求,都会起一个协程去处理.在处理协程中,也会起很多协程去访问资源,比如数据库,比如RPC,这些协程还需要访问请求维度的一些信息比如说请求方的身份,授权信息等等.当一个请求 ...
- Apache Flink on K8s:四种运行模式,我该选择哪种?
1. 前言 Apache Flink 是一个分布式流处理引擎,它提供了丰富且易用的API来处理有状态的流处理应用,并且在支持容错的前提下,高效.大规模的运行此类应用.通过支持事件时间(event-ti ...
- 快速了解前端开发HTML的正确姿势
摘要:web前端开发(也称为客户端开发)主要是通过html,CSS和JavaScript等前端技术,实现网站在客服端的正确显示及交互功能. 一.web标准介绍 web标准: w3c:万维网联盟组织,用 ...
- 趣图:普通人讲故事 VS 程序员讲故事
扩展阅读 趣图:我说自己菜 vs 大佬说自己菜 趣图:客户需求VS客户预算 趣图:在外行人眼中的程序员 如何处理前任程序员留下的代码 一个故事讲清楚NIO
- linux上部署springboot项目
1.安装jdk,请参考个人博客linux安装jdk 2.安装mysql,请参考个人博客 linux安装mysql 3.项目打包(使用idea) 打开项目,点击idea右边Maven Projects菜 ...
- SQL Server 子查询遇到的坑
这两天改 Bug 时使用 Sql Server 的子查询遇到了一些问题,特此记录一下,之前用 MySQL 比较多,按照 MySQL 的语法其实是没有问题的. 以下面这张表为例: 执行以下 SQL: s ...