zoukankan      html  css  js  c++  java
  • ●BZOJ 3126 [Usaco2013 Open]Photo

    题链:

    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;
    }
    

      

  • 相关阅读:
    LeetCode周赛#206
    CET-6备考丨词组、佳句积累
    界面设计9.24第一次课
    图像超分辨率重建
    OpenGL和计算机图形学初步认识
    OpenGL装gult库
    安装java
    vs2019配置Opengl
    最长上升子序列(最长递增子序列)LIS
    c++科学计数法 、long long的范围
  • 原文地址:https://www.cnblogs.com/zj75211/p/8168933.html
Copyright © 2011-2022 走看看