HAOI2014 贴海报 浮水法

好久没更博客了,最近回来刷题。今天做了一道2014年河南省选【贴海报】,用到了浮水法,写篇博客。

适用:浮水法主要使用于有覆盖的染色问题。

方法本身的思想不难理解:(以【贴海报】为背景)想象所有的海报都漂浮在水面上。如果一张海报的部分上方没有被其他海报阻挡,则上浮。

如果这部分能上浮到最高处,那么这部分就是可以被观察到的一部分。

HAOI2014 贴海报 浮水法_第1张图片

题目

题目描述

Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论。为了统一管理,城市委员会为选民准备了一个张贴海报的electoral墙。

张贴规则如下:

  1. electoral墙是一个长度为N个单位的长方形,每个单位记为一个格子;

  2. 所有张贴的海报的高度必须与electoral墙的高度一致的;

  3. 每张海报以“A B”表示,即从第A个格子到第B个格子张贴海报;

  4. 后贴的海报可以覆盖前面已贴的海报或部分海报。

现在请你判断,张贴完所有海报后,在electoral墙上还可以看见多少张海报。

输入格式

第一行: N M 分别表示electoral墙的长度和海报个数

接下来M行: Ai Bi 表示每张海报张贴的位置

输出格式

输出贴完所有海报后,在electoral墙上还可以看见的海报数。

输入输出样例

输入 #1
100 5
1 4
2 6
8 10
3 4
7 10
输出 #1
4 

【约束条件】

1 0<= N <= 10000000 1<=M<=1000 1<= Ai <= Bi <=10000000

所有的数据都是整数。数据之间有一个空格

分析

很显然,这道题目中有覆盖的问题,那么我们可以用到浮水法来处理。解具体的题目有几个注意的地方,结合代码来看。

  1. 读入时,每个右端点加上1。因为这个端点也覆盖了海报。
  2. 倒序处理(j 从大到小)。这是显然的,因为题目存在覆盖的顺序,从上到下处理。
  3. 题目的提示中指出,相同的海报分两处被看见算一张海报,所以我们引入一个vis数组,来表示该海报是否已经被算入ans答案中。
  4. while 和 if 中是否取等号有明显区别,留给读者自行画图思考。

程序

 1 #include
 2 using namespace std;
 3 const int MAXN = 10000000 + 10, MAXM = 1000 + 10;
 4 int n, m, ans = 0, j, A[MAXM], B[MAXM];
 5 bool vis[MAXM];
 6 void work(int a, int b, int l)
 7 {
 8     if (vis[j])
 9         return;
10     while (l <= m && (a >= B[l] || b <= A[l]))
11         ++l;
12     if (l > m)
13         ans++, vis[j] = true;
14     if (a < A[l] && A[l] < b)
15         work(a, A[l], l+1);
16     if (b > B[l] && B[l] > a)
17         work(B[l], b, l+1);
18 }
19 int main()
20 {
21     cin >> n >> m;
22     for (int i = 1; i <= m; i++)
23     {
24         cin >> A[i] >> B[i];
25         ++B[i];
26     }
27     for (j = m - 1; j >= 1; j--)
28         work(A[j], B[j], j+1);
29     cout << ans+1 << endl;
30     return 0;
31 }

 

转载于:https://www.cnblogs.com/OIerPrime/p/10743044.html

你可能感兴趣的:(HAOI2014 贴海报 浮水法)