[USACO13OPEN]照片Photo

题目描述

农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\)。

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

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

输入输出格式

输入格式:

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\):差分约束

虽然这个题卡差分约束,但我不应该没想到的,应当警醒。

让每个位置代表这个位置之前有多少头牛,有向边方向为大于等于,连好边了跑最短路就可以了。


解题思路\(2\):\(dp\)

\(dp\)的思路很妙,我最开始想过一会儿\(dp\),但是始终无法直接通过区间来划分状态进行转移。

考虑对位置进行\(dp\),规定\(dp_i\)表示位置\(i\)强制放牛的最大牛数量。

考虑某位置\(i\)强制选后可以转移的区间,设\(L_i\)和\(R_i\)为转移的两个区间

\(R_i\)为覆盖这个点的所以区间的最左左端点\(-1\)

\(L_i\)为区间右端点在这个点\(i\)左边的区间的最右左端点

以上两个东西仔细想想应该不难想明白,求法也不难,就是先打好位置标记,然后扫描前缀或后缀最大值。

转移有

\[dp_i=\max_{L_i\le j \le R_i}dp_j+1
\]

用一个单调队列维护或者线段树都行(很显然转移区间有单调性)

这里强调一种写法,因为我们要找到最后一个强制放的位置,所以要枚举答案,但是还要判一下会不会无解,不太好弄。

不如搞一个虚的\(n+1\)的位置,最后答案就在\(n+1\)啦

Code:

#include <cstdio>
const int N=2e5+10;
int dp[N],L[N],R[N],n,m,q[N],l,r;
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
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",&l,&r);
L[r+1]=max(L[r+1],l);
R[r]=min(R[r],l-1);
}
l=r=0;
for(int i=1;i<=n+1;i++) L[i]=max(L[i-1],L[i]);
for(int i=n;i;i--) R[i]=min(R[i+1],R[i]);
for(int i=1;i<=n+1;i++)
{
while(l<=r&&L[i]>q[l]) l++;
for(int j=max(L[i],q[r]+1);j<=R[i];j++)
{
while(l<=r&&dp[j]>=dp[q[r]]) r--;
q[++r]=j;
}
if(l<=r) dp[i]=~dp[q[l]]?dp[q[l]]+1:-1;
else dp[i]=-1;
}
printf("%d\n",~dp[n+1]?dp[n+1]-1:-1);
return 0;
}

2018.10.22

洛谷 P3084 [USACO13OPEN]照片Photo 解题报告的更多相关文章

  1. 洛谷3084 [USACO13OPEN]照片Photo

    原题链接 神仙\(DP\)啊... 题解请移步隔壁大佬的博客\(QAQ\) #include<cstdio> using namespace std; const int N = 2e5 ...

  2. 洛谷P3084 [USACO13OPEN]照片

    题目 \(DP\) 设状态\(dp[i]\)为\(i\)位置放了斑点牛,前\(i\)个位置能得到的最多的牛. 有方程\(dp[i]=max(dp[j]+1,dp[i])\),而我们并不知道什么\(j\ ...

  3. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  4. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  5. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  6. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

  7. 洛谷1303 A*B Problem 解题报告

    洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...

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

    题目链接:传送门 题目: 题目描述 Farmer John has decided to assemble a panoramic photo of a lineup of his N cows ( ...

  9. P3084 [USACO13OPEN]照片Photo

    题目描述 农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N. 于是约翰拍摄了M(1 <= M <= 100,00 ...

随机推荐

  1. Python数值

    一.python数值类型 python数值类型有以下四种: int(整数) float(浮点数) complex(复数) bool(布尔型) 注意:python3取消了long型.  二.python ...

  2. python__标准库 : urllib2

    urllib,urllib2 urllib库主要用 urlencode()把字典转换成url的get参数或者post参数 或者用 quote() 进行编码unquote进行解码 用urllib2.Pr ...

  3. ReentrantLock详解

    ReentrantLock概述 ReentrantLock是Lock接口的实现类,可以手动的对某一段进行加锁.ReentrantLock可重入锁,具有可重入性,并且支持可中断锁.其内部对锁的控制有两种 ...

  4. HBase学习(三):数据模型

    和传统的关系型数据库类似,HBase以表(Table)的方式组织数据.HBase的表由行(Row)和列(Column)共同构成,与关系型数据库不同的是HBase有一个列族(ColumnFamily)的 ...

  5. AB PLC 编程之状态机

    AB的程序设计和西门子有点PLC不大一样,在AB中没有RS指令,所以主要用move指令来作步进.今天我们就用Move指令写个AB的程序,和西门子比,有哪些不同. 控制任务 很简单的一个状态机.初始步为 ...

  6. Flask初学者:url_for

    URL反转:反转是指通过视图函数名称得到其对应的URL(有反转也就有正转,即通过URL得到视图函数返回的内容,也就是我们平时的访问网页了),需要“url_for(endpoint, **values) ...

  7. spring-boot整合ehcache实现缓存机制

    EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. ehcache提供了多种缓存策略,主要分为内存和磁盘两级,所以无需担心 ...

  8. C++11中std::bind的使用

    std::bind: Each argument may either be bound to a value or be a placeholder: (1).If bound to a value ...

  9. Oracle 完全理解connect by-详细脚本-可实战

    狒狒Q971751392 未来星开发团队--狒狒(QQ:9715234) oracle树查询的最重要的就是select…start with…connect by…prior语法了.依托于该语法,我们 ...

  10. Django数据模型--字段详解

    一.字段 1.CharField: 字段数据类型为字符串 class Test(models.Model): test = models.CharField(max_length=) 2.Intege ...