Bzoj 3126[Usaco2013 Open]Photo 题解

3126: [Usaco2013 Open]Photo

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 335  Solved: 169
[Submit][Status][Discuss]

Description

Farmer John has decided to assemble a panoramic photo of a lineup of his N cows (1 <= N <= 200,000), which, as always, are conveniently numbered from 1..N. Accordingly, he snapped M (1 <= M <= 100,000) photos, each covering a contiguous range of cows: photo i contains cows a_i through b_i inclusive. The photos collectively may not necessarily cover every single cow. After taking his photos, FJ notices a very interesting phenomenon: each photo he took contains exactly one cow with spots! FJ was aware that he had some number of spotted cows in his herd, but he had never actually counted them. Based on his photos, please determine the maximum possible number of spotted cows that could exist in his herd. Output -1 if there is no possible assignment of spots to cows consistent with FJ's photographic results. 

 

给你一个n长度的数轴和m个区间,每个区间里有且仅有一个点,问能有多少个点

Input

 * Line 1: Two integers N and M.

* Lines 2..M+1: Line i+1 contains a_i and b_i.

Output

* Line 1: The maximum possible number of spotted cows on FJ's farm, or -1 if there is no possible solution.

Sample Input

5 3
1 4
2 5
3 4

INPUT DETAILS: There are 5 cows and 3 photos. The first photo contains cows 1 through 4, etc.

Sample Output

1
OUTPUT DETAILS: From the last photo, we know that either cow 3 or cow 4 must be spotted. By choosing either of these, we satisfy the first two photos as well
 
  不知道对于这道题有没有人和我一样,想到了 [Apio2012]Guard 这道题,题目设置还是挺类似的,然而正解之间貌似毫不相关。
  这道题更多的是偏向于动归题,如果知道是动归的话那么转移方程一般也就写的出来了:
    f[i]=MAX(f[j])+1
  看着挺简单的,但是j的取值范围的确定是这道题的关键,为此我们可以在纸上自己模拟一些情况,然后我们可以注意到,能够更新这个点且合法的点一定在离当前点最近的完整区间的左端点及其之后,且一定在离当前点最近的右端点之前。而我们又发现这个区间对于每个点都是单调的,所以我们可以打出来单调队列来进行优化。因此这道题就差不多搞完了。
  最后一点,不合法的情况的判断。如果说当前点的可选取的左边界大于右边界,那么,这个点我们是不能去放置的,我们应把它赋为极小值,注意,此时只是在这个点放置不合法,不代表整个题都不合法。而如果出现了对于整个题目设置都不合法的情况他后面的区间都会受他影响而变为负值。这一点语言不好表述,请读者自行手推。
 1 #pragma GCC optimze("O3")
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<cmath>
 9 #include<map>
10 #include<vector>
11 #define N 200005
12 using namespace std;
13 int n,m,r[N],l[N],q[N*2],en,hea=1,f[N];
14 int main()
15 {
16     scanf("%d%d",&n,&m);
17     for(int i=1;i<=n+1;i++)
18         r[i]=i-1;
19     for(int i=1;i<=m;i++)
20     {
21         int x,y;
22         scanf("%d%d",&x,&y);
23         l[y+1]=max(l[y+1],x);
24         r[y]=min(r[y],x-1);
25     }
26     for(int i=2;i<=n+1;i++)
27         l[i]=max(l[i],l[i-1]);
28     for(int i=n;i>0;i--)
29         r[i]=min(r[i],r[i+1]);
30     en++;
31     q[en]=0;
32     for(int i=1;i<=n+1;i++)
33     {
34         for(int j=r[i-1]+1;j<=r[i];j++)
35         {
36             while(hea<=en&&f[q[en]]<f[j])en--;
37             en++;
38             q[en]=j;
39         }
40         while(hea<=en&&q[hea]<l[i])hea++;
41         if(hea>en)
42             f[i]=-0x7ffffff;
43         else
44             f[i]=f[q[hea]]+1;
45     }
46     if(f[n+1]>=0)printf("%d\n",f[n+1]-1);
47     else
48         printf("-1\n");
49     return 0;
50 }
View Code

 

posted @ 2017-09-24 20:32  Hzoi_joker  阅读(347)  评论(0编辑  收藏  举报