题解: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\) ,这也是唯一确定的。

揆诸上例与题面自顶向下给权的性质,我们容易发现:

  1. 对于任意一个未确定的结点,它的可能取值范围总是 \((0,x_i]\) ,

    其中, \(x_i\) 是由树的结构与已知点权共同决定的。

  2. 一个点的权能被唯一确定,当且仅当其取值范围为 \((x_i - 1, x_i]\)

  3. 当我们确定了 \(k\) 个结点的取值后,剩余的未确定结点的取值范围就会变化为 \((k, x_i]\)

  4. 确定点权的顺序总是从小到大的。

(写成左开右闭的形式仅仅是为了规避区间左右端点相等的写法,没别的意思)

接下来只要模拟上述的推理即可。

我们可以首先一次 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的更多相关文章

  1. 【BZOJ2799】[Poi2012]Salaries 乱搞

    [BZOJ2799][Poi2012]Salaries Description 给出一棵n个结点的有根树,结点用正整数1~n编号.每个结点有一个1~n的正整数权值,不同结点的权值不相同,并且一个结点的 ...

  2. [BZOJ2799][Poi2012]Salaries

    2799: [Poi2012]Salaries Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 91  Solved: 54[Submit][Statu ...

  3. [POI2012]Salaries

    题目大意: 给定一棵n带权树,每个点的权值在[1,n]范围内且互不相等,并满足子结点的权值一定小于父结点. 现在已知一个包含根结点的联通块中个点的权值,求剩下哪些点的权值能够被求出,并求出这些权值. ...

  4. bzoj 2799 [Poi2012]Salaries 性质+二分

    题目大意 给出一棵n个结点的有根树,结点用正整数1~n编号. 每个结点有一个1~n的正整数权值,不同结点的权值不相同, 并且一个结点的权值一定比它父结点的权值小(根结点的权值最大,一定是n). 现在有 ...

  5. POI2012题解

    POI2012题解 这次的完整的\(17\)道题哟. [BZOJ2788][Poi2012]Festival 很显然可以差分约束建图.这里问的是变量最多有多少种不同的取值. 我们知道,在同一个强连通分 ...

  6. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  7. [Poi2012]Festival 题解

    [Poi2012]Festival 时间限制: 1 Sec  内存限制: 64 MB 题目描述 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: 1. 给出a,b (1 ...

  8. 【题解】 [POI2012]FES-Festival (差分约束)

    懒得复制题面,戳我戳我 Question: (因为网上找不到好的翻译,这里简单复述一下) 告诉你\(m1+m2\)个约束条件,然后要你找出\(X_1-X_n\)这些数字,求满足要求的数列中不同的数字个 ...

  9. BZOJ2802: [Poi2012]Warehouse Store

    2802: [Poi2012]Warehouse Store Time Limit: 10 Sec  Memory Limit: 64 MBSec  Special JudgeSubmit: 121  ...

随机推荐

  1. boot 项目启动报Cannot datermine embedded database driver class for database type NONE

    部署boot项目时报Cannot datermine embedded database driver class for database type NONE数据库链接什么的也都没有问题,经过百度 ...

  2. 面试官问我:看过sharding-jdbc的源码吗?我吧啦吧啦说了一通!!

    写在前面 在产品初期快速迭代的过程中,往往为了快速上线而占据市场,在后端开发的过程中往往不会过多的考虑分布式和微服务,往往会将后端服务做成一个单体应用,而数据库也是一样,最初会把所有的业务数据都放到一 ...

  3. 详解JVM中的内存模型是什么?

    强烈推荐 不管是找工作还是提升水平,都建议读一下<深入理解Java虚拟机>这本书,详细讲解了JVM中的内存管理.类加载过程.垃圾回收以及最重要的性能调优实战. 本博客也是参考了这本书,有不 ...

  4. Linux下Shell日期的格式,你知道几种?

    Linux下Shell日期的格式,你知道几种? 不管是哪种语言,日期/时间都是一个非常重要的值.比如我们保存日志的时候,往往是某个前缀再加上当前时间,这样日志文件名称就可以做到唯一. 在Shell环境 ...

  5. Django+pycharm+mysql 实现用户登录/注册(Django五)

    首先是让Django项目与mysql数据库初步建立连接 具体做法见:pycharm连接mysql(注意其中第二步MySQL驱动最好安装最新版的) 这里讲一下我在做这一步遇到的问题.一般Driver 那 ...

  6. oracle之三rman 维护

    rman 维护 11.1 rman 使用和维护 11.2 list 命令一览 1)RMAN> list backup; 2)RMAN> list backup of tablespace ...

  7. python3 for

    当range中只有一个参数时,此参数表示终点,但不包括.(从0开始) 当range中有两个参数时,分别表示起点和终点.(左闭但不包括终点) 当range中有三个参数时,分别表示起点和终点,和步长,意思 ...

  8. RabbitMQ消息积压的几种解决思路

    在日常工作中使用RabbitMQ偶尔会遇不可预料的情况导致的消息积压,一般出现消息积压基本上分为几种情况: 消费者消费消息的速度赶不上生产速度,这总问题主要是业务逻辑没设计好消费者和生产者之间的平衡, ...

  9. 仿苏宁移动web页面 自适应 rem&less

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  10. hystrix源码小贴士之调用异常处理

    executeCommandAndObserve方法处理onerror异常. return execution.doOnNext(markEmits) .doOnCompleted(markOnCom ...