poj 2373 单调队列优化背包
思路:我们用单调队列保存2*b<=i-j<=2*a中的最大值。那么队列头就是最大值,如果队头的标号小于i-2*b的话,就出队,后面的肯定用不到它了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define inf 10000010 #define Maxn 1010 #define Min(a,b) (a)>(b)?(b):(a) using namespace std; int dp[1000010],que[1000010],head,rear,interv[1200010]; struct Inter{ int l,r; int operator<(const Inter &temp) const { return l<temp.l; } }p[Maxn]; int main() { int n,l,i,j,t,a,b; while(scanf("%d%d",&n,&l)!=EOF) { scanf("%d%d",&a,&b); memset(interv,1,sizeof(interv)); for(i=1;i<=n;i++) { scanf("%d%d",&p[i].l,&p[i].r); memset(interv+p[i].l+1,0,(p[i].r-p[i].l-1)*sizeof(interv[0])); } dp[0]=0; head=1,rear=0; for(i=2;i<=l;i++) { dp[i]=inf; j=i-2*a; if(j<0) continue; while(head<=rear&&dp[j]<=dp[que[rear]]) rear--; if(interv[j]) que[++rear]=j; if(que[head]<i-2*b&&head<=rear) head++; if(!interv[i]||(i&1)) continue; if(head<=rear) dp[i]=dp[que[head]]+1; } if(dp[l]>=inf) printf("-1\n"); else printf("%d\n",dp[l]); } return 0; }