[USACO13OPEN]照片Photo

题目描述

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(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N。

于是约翰拍摄了M(1 <= M <= 100,000)张照片,每张照片都覆盖了连续一段奶牛:第i张照片中包含了编号a_i 到 b_i的奶牛。但是这些照片不一定把每一只奶牛都拍了进去。

在拍完照片后,约翰发现了一个有趣的事情:每张照片中都有一只身上带有斑点的奶牛。约翰意识到他的牛群中有一些斑点奶牛,但他从来没有统计过它们的数量。 根据照片,请你帮约翰估算在他的牛群中最多可能有多少只斑点奶牛。如果无解,输出“-1”。

Input

输入输出格式

输入格式:

  • Line 1: Two integers N and M.
  • Lines 2..M+1: Line i+1 contains a_i and b_i.

输出格式:

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

输入输出样例

输入样例#1:

5 3
1 4
2 5
3 4

输出样例#1:

1 题解:这道题,要画画图理解才行。其实就是要求

1.在每个区间里面都必须要有一棵树被砍。

2.并且每个区间里面都必须只有一棵树被砍。
这两句话很关键。于是我们可以根据这两个条件做dp。
首先我们设f[i]为前i个树满足条件且最多能有多少树没有被砍,便有f[i]=max(f[j])+1
那么j的范围呢?
根据条件1,我们可以确定左边界
(因为必须选,那么上一个区间也一定要选,故j一定是>=最靠近i左边的区间的左坐标)
根据条件2,我们可以确定右边界。
(因为必须选一个,所以包含i的区间里面的任意一个j都不能转移,即j<=包含i的区间的最小的左坐标)
故我们可以根据这些限定用单调队列来优化原来的dp方程。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 struct Messi
 7 {
 8     int l,r;
 9 }a[200103];
10 int n,m,rp[200103],lp[200101],q[500101],f[200101];
11 int main()
12 {int i,j,head,tail;
13 //freopen("search.in","r",stdin);
14 //freopen("search.out","w",stdout);
15     cin>>n>>m;
16     for (i=1;i<=n+1;i++)
17     rp[i]=i-1;
18      for (i=1;i<=m;i++)
19      {
20          scanf("%d%d",&a[i].l,&a[i].r);
21          lp[a[i].r+1]=max(lp[a[i].r+1],a[i].l);
22          rp[a[i].r]=min(rp[a[i].r],a[i].l-1);
23      }
24       for (i=n;i>=1;i--) rp[i]=min(rp[i],rp[i+1]);
25       for (i=2;i<=n+1;i++) lp[i]=max(lp[i],lp[i-1]);
26       j=1;
27       head=tail=1;
28       for (i=1;i<=n+1;i++)
29       {
30           while (j<=rp[i]&&j<=n)
31           {
32                if (f[j]==-1)
33                {
34                    j++;
35                    continue;
36              }
37             while (f[j]>f[q[tail]]&&tail>=head) tail--;
38             ++tail;
39             q[tail]=j;
40             j++;
41         }
42         while (q[head]<lp[i]&&head<=tail) head++;
43          if (head<=tail) f[i]=f[q[head]]+(i!=n+1?1:0);
44          else f[i]=-1;
45       }
46       if (f[n+1]!=-1)
47     cout<<f[n+1];
48     else cout<<-1;
49 }

				
时间: 2024-10-11 00:26:38

[USACO13OPEN]照片Photo的相关文章

[USACO13OPEN]照片Photo [动态规划 单调队列]

[USACO13OPEN]照片Photo 这题好烧脑... #include<bits/stdc++.h> using namespace std; #define ll long long #define rg register #define Max(x,y) ((x)>(y)?(x):(y)) #define Min(x,y) ((x)>(y)?(y):(x)) const int N=2e5+5,M=1e5+5,inf=0x3f3f3f3f,P=19650827; int

【DP专题】——[USACO13OPEN]照片Photo

这道题是道非常好的动规题,不难但思考过程受益很大. [9/25日更新:鸽了俩个月回来补档了] 题目描述 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 <

P3084 [USACO13OPEN]照片Photo

题目描述 农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N. 于是约翰拍摄了M(1 <= M <= 100,000)张照片,每张照片都覆盖了连续一段奶牛:第i张照片中包含了编号a_i 到 b_i的奶牛.但是这些照片不一定把每一只奶牛都拍了进去. 在拍完照片后,约翰发现了一个有趣的事情:每张照片中都有一只身上带有斑点的奶牛.约翰意识到他的牛群中有一些斑点奶牛,但他从来没有统计过它们的数量. 根据照片,请你帮约翰估算在他的

P3084 [USACO13OPEN]照片Photo (dp+单调队列优化)

题目链接:传送门 题目: 题目描述 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

Luugu 3084 [USACO13OPEN]照片Photo

很神仙的dp...假装自己看懂了,以后回来复习复习... 设$f_{i}$表示从$1$到$i$,且$i$这个点必放的最小代价. 一个区间有两个限制条件:至少放一个,至多放一个. 因为一个区间至多要放一个,所以所有包含这个点的区间都不能再放,设$r_{i}$表示包含这个点的区间中最小的左端点$ - 1$. 因为一个区间至少要放一个,所以不能有区间中一个都不放,设$l_{i}$表示整个区间在当前点之前的最大的左端点. 这样子就有了转移方程:$f_{i} = max(f_{j}) + 1$  $(l_

【题解】[USACO] 照片Photo

[题解][USACO] 照片Photo [题目大意] 在\(1\)~\(N\)的序列上有\(M\)个区间,使得这\(M\)个小区间每个覆盖了且仅覆盖了一个点,求最多点数,如果无解,输出\(-1\). [分析] 刚开始做的时候我是懵的...不管三七二十一开始想差分约束系统,无奈没那么好的思维,没想出来... 一翻题解,,\(WOC!!!\)这是什么神仙\(DP?\)真的是学到了... 我们设\(f[i]\)表示序列的第\(i\)位是一个点时,序列\(1\)~\(i\)的最多点数. 那么\(dp\)

C# 编码标准(三)

一.代码注释 1.文档型注释 该类注释采用.Net已定义好的Xml标签来标记,在声明接口.类.方法.属性.字段都应该使用该类注释,以便代码完成后直接生成代码文档,让别人更好的了解代码的实现和接口.[示例]如 ///<summary>MyMethod is a method in the MyClass class. ///<para>Here's how you could make a second paragraph in a description. ///<see c

SQL中的Null深入研究分析

虽然熟练掌握SQL的人对于Null不会有什么疑问,但总结得很全的文章还是很难找,看到一篇英文版的, 感觉还不错. Tony Hoare 在1965年发明了 null 引用, 并认为这是他犯下的"几十亿美元的错误". 即便是50年后的今天, SQL中的 null 值还是导致许多常见错误的罪魁祸首. 我们一起来看那些最令人震惊的情况. Null不支持大小/相等判断 下面的2个查询,不管表 users 中有多少条记录,返回的记录都是0行: select * from users where

C#项目代码规范

.Net 项目代码风格要求 PDF版下载:项目代码风格要求V1.0.pdf 代码风格没有正确与否,重要的是整齐划一,这是我拟的一份<.Net 项目代码风格要求>,供大家参考. 1. C# 代码风格要求 1.1注释 类型.属性.事件.方法.方法参数,根据需要添加注释. 如果类型.属性.事件.方法.方法参数的名称已经是自解释了,不需要加注释:否则需要添加注释. 当添加注释时,添加方式如下图所示: 1.2 类型(类.结构.委托.接口).字段.属性.方法.事件的命名 优先考虑英文,如果英文没有合适的单