●BZOJ 3126 [Usaco2013 Open]Photo
2018-01-01 21:11
405 查看
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=3126
题解:
单调队列优化DP,神奇。。
(好像某次考试考过,当时我用了差分约束+SPFA优化,然后过了。。。)
记 L[i] 表示i左边没有覆盖i点的区间中的最大的左端点
R[i] 表示覆盖i的区间中的最小的左端点的前一个位置,
那么,如果在i位置放一个点的话,在L[i]~R[i]里面也必须要放一个点。
(这两个数组可以O(N)计算前后缀最大最小值得到。)
即定义 DP[i] 为i位置放点时的总点数,
转移:DP[i]=max(DP[j])+1 (L[i]<=j<=R[i])
然后可以用单调队列优化。
和普通的单调队列有点不同,因为多了一个R[i]这个转移的右端点限制。
其实本质还是相同的~~
考虑到L[i],R[i]都单增,
所以在原来队列的首尾指针l,r的基础上多开一个rr指针就好了。
代码:
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 200050 using namespace std; int L[MAXN],R[MAXN],F[MAXN]; int N,M; int main(){ static int Q[MAXN],l,r,_r; scanf("%d%d",&N,&M); for(int i=1;i<=N+1;i++) R[i]=i-1; for(int i=1,l,r;i<=M;i++){ scanf("%d%d",&l,&r); L[r+1]=max(L[r+1],l); R[r]=min(R[r],l-1); } for(int i=2;i<=N+1;i++) L[i]=max(L[i-1],L[i]); for(int i=N;i>=1;i--) R[i]=min(R[i],R[i+1]); l=_r=r=1; Q[1]=0; for(int i=1;i<=N+1;i++){ while(_r<=R[i]&&_r<=N){ if(F[_r]==-1){_r++; continue;} while(l<=r&&F[Q[r]]<=F[_r]) r--; Q[++r]=_r; _r++; } while(l<=r&&Q[l]<L[i]) l++; if(l<=r) F[i]=F[Q[l]]+(i!=N+1?1:0); else F[i]=-1; } printf("%d",F[N+1]); return 0; }
相关文章推荐
- bzoj 3126: [Usaco2013 Open]Photo——单调队列优化dp
- 数据结构(线段树):BZOJ 3126: [Usaco2013 Open]Photo
- bzoj 3126: [Usaco2013 Open]Photo (DP+单调队列)
- [BZOJ] 3126: [Usaco2013 Open]Photo
- bzoj 3126: [Usaco2013 Open]Photo dp
- 单调队列 bzoj3126 [Usaco2013 Open]Photo
- bzoj3126[Usaco2013 Open]Photo 单调队列优化dp
- bzoj3126 [Usaco2013 Open]Photo
- [bzoj3126][USACO2013]Photo_动态规划_单调队列
- BZOJ3126: [Usaco2013 Open]Photo
- BZOJ 3128 Usaco2013 Open Figure Eight
- 【BZOJ】【3697】采药人的路径&【3127】【USACO2013 Open】Yin and Yang
- BZOJ 3127 [Usaco2013 Open]Yin and Yang(树点分治)
- 照片 usaco 2013 open photo
- bzoj3299 [USACO2011 Open]Corn Maze玉米迷宫
- [bzoj3404] [Usaco2009 Open]Cow Digit Game又见数字游戏
- BZOJ 1711 [Usaco2007 Open]Dining吃饭 最大流
- bzoj 3298: [USACO 2011Open]cow checkers 威佐夫博弈
- 【BZOJ4094】【Usaco2013 Dec】Optimal Milking(线段树)
- bzoj 1573 [Usaco2009 Open]牛绣花cowemb 计算几何 树状数组