题目描述:
有 N 头牛站成一行,被编队为1、2、3…N,每头牛的身高都为整数。 当且仅当两头牛中间的牛身高都比它们矮时,两头牛方可看到对方。
现在,我们只知道其中最高的牛是第 P 头,它的身高是 H ,剩余牛的身高未知。 但是,我们还知道这群牛之中存在着 M
对关系,每对关系都指明了某两头牛 A 和 B 可以相互看见。 求每头牛的身高的最大可能值是多少。
输入格式:
第一行输入整数N,P,H,M,数据用空格隔开。 接下来M行,每行输出两个整数 A 和 B ,代表牛 A 和牛 B
可以相互看见,数据用空格隔开。
输出格式:
一共输出 N 行数据,每行输出一个整数。 第 i 行输出的整数代表第 i 头牛可能的最大身高。
数据范围:
1≤N≤10000, 1≤H≤1000000, 1≤A,B≤10000, 0≤M≤10000
题目分析如下:(摘自《算法竞赛进阶指南》)
题目中的 M 对关系带给我们的信息实际上是牛之间身高的相对大小关系。 具体来说,我们建立一个数组 C,数组中其实全为0。若存在一对关系指明: A 和 B 可以相互看见(设A < B),则把数组 C 中 下标为 A + 1 到 B - 1 的数都减去1,意思是在 A 和 B 中间的牛,身高至少要比它们小 1。因为第 P 头牛是最高的,所以最终 C[P] 一定为0。其他的牛与第 P 头牛的身高差距就体现在数组 C 中。换言之,最后第 i 头牛的身高就等于 H + C[i]。
AC代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;
const int MAXN = 1e4+10;
int n, p, h, m;
int exited[MAXN];
LL c[MAXN];
// 初始数组为0 说明高度都相同,以h为基准进行修改
int main() {
scanf("%d %d %d %d", &n, &p, &h, &m);
int a, b;
while(m--) {
scanf("%d %d",&a, &b);
if(a > b) swap(a, b);
// 保证 a < b
if(exited[a] == b) continue;
// 在数组 exited 中查找(a, b)键值对是否出现
c[a+1] --, c[b]++;
// 区间内的高度降1 利用差分的性质
exited[a] = b;
// 标记(a, b)键值对已出现过
}
c[1] = h + c[1];
printf("%lld\n", c[1]);
for(int i = 2; i <= n; i++) {
c[i] = c[i-1] + c[i];
printf("%lld\n", c[i]);
}
return 0;
}