f(i)=min{f(j)+(D(j)<=D(i))} (max(1,i-k)<=j<=i)
有两个变量,很难用单调队列,但是(引用):
如果fi<fj,i一定比j优秀。因为如果heighti≥heightj就不用说了,如果heighti<heightj,i可以花1的代价跳到高的地方,顶多和j一样,不会比j差。
如果fi=fj,那当然就是谁的height高谁优秀。
双关键字搞一下就好了。
#include<cstdio> using namespace std; #define N 1000001 struct Point{int x,y;}; bool operator <= (const Point &a,const Point &b){return a.x!=b.x?a.x<b.x:a.y>=b.y;} int n,m,K,q[N]; Point dp[N]; int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&dp[i].y); scanf("%d",&m); for(;m;--m) { scanf("%d",&K); int head=1,tail=1; dp[1].x=0; q[1]=1; for(int i=2;i<=K;++i) { dp[i].x=dp[q[head]].x+(dp[q[head]].y<=dp[i].y); while(dp[i]<=dp[q[tail]] && tail>=head) --tail; q[++tail]=i; } for(int i=K+1;i<=n;++i) { dp[i].x=dp[q[head]].x+(dp[q[head]].y<=dp[i].y); if(q[head]<i-K+1) ++head; while(dp[i]<=dp[q[tail]] && tail>=head) --tail; q[++tail]=i; } printf("%d ",dp[n].x); } return 0; }