您的位置:首页 > 运维架构

[BZOJ] 3126: [Usaco2013 Open]Photo

2017-09-21 19:02 579 查看

3126: [Usaco2013 Open]Photo

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 318  Solved: 162
[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.

HINT

 

Source

Gold

 

Analysis

这翻译质量不敢恭维= =最后还是自己看了原文

= ,=

FJ对着一队奶牛拍了一堆照片

巧合的是,每张照片中都恰好有一只奶牛

现在给你每张照片里最左边的奶牛和最右边的奶牛的编号

问你在已知条件下最多能有多少奶牛?

= 。=

这道题有点毒

先说分类:DP,单调队列优化DP

合理性:

  状态表示为 F[ i ],表示只考虑前 i 只奶牛,且第 i 只奶牛必取,特殊情况下对 F[ i ] 取特殊值以区分

  显然这样是没有后效性的

因此整个主线就基本明朗了:后面的继承前面的

那么就有一个被继承的区域,我们在这个区域里面选择最大值继承

好吧,根据题目,我们知道

  每张照片里面 仅有且必有 一只有斑点的奶牛

那么我们继承就有这么个原则了:

1. 每个区间都必须要取一个点,可以共用;

2. 每个区间内不能重复取点

那么继承从距离 i 当前区间最近的左边的那个区间开始,直到 i 当前这个区间的最左的左端点结束

/**************************************************************
Problem: 3126
User: child
Language: C++
Result: Accepted
Time:184 ms
Memory:4444 kb
****************************************************************/

#include<cstdio>
#include<iostream>
#define maxn 202020
using namespace std;

int n,m,a,b,r[maxn],l[maxn],DP[maxn];
int que[maxn],head,tail;

int main(){
scanf("%d%d",&n,&m);

for(int i = 1;i <= n+1;i++) r[i] = i-1;

for(int i = 1;i <= m;i++){
scanf("%d%d",&a,&b);
r[b] = min(r[b],a-1);
l[b+1] = max(l[b+1],a);
}

for(int i = n;i;i--)
r[i] = min(r[i],r[i+1]);

for(int i = 2;i <= n+1;i++)
l[i] = max(l[i],l[i-1]);

for(int i = 1;i <= n+1;i++){
for(int k = l[i];k <= r[i];k++){
while(tail < head && DP[que[head]] <= DP[k]) head--;
que[++head] = k;
}

while(tail < head && que[tail+1] < l[i]) tail++;

if(tail == head) DP[i] = -1e9;
else DP[i] = DP[que[tail+1]] +1;
}

//  for(int i = 0;i <= n+1;i++) printf("%d ",DP[i]);
//  cout << endl;

if(DP[n+1] >= 0) printf("%d\n",DP[n+1]-1);
else printf("-1\n");

return 0;
}
= =  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: