BZOJ3831:[Poi2014]Little Bird dp+单调队列
思路:
一开始是用的线段树优化dp,具体的就不说了.
我一开始觉得有的需要+1,有的不需要加,单调队列没办法做.
不过有一条性质,就是如果两条决策,其中一个的步数已经比另一个决策少,那么我们选择这个决策是一定不劣于另一个决策的.
否则若步数相同,我们当然选择保留高度较高的那个决策.
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;
namespace Fio{
inline int getc(){
static const int L=1<<15;static char buf[L],*S=buf,*T=buf;
if(S==T){T=(S=buf)+fread(buf,1,L,stdin);if(S==T)return EOF;}
return*S++;
}
template<typename T>inline void Get(T&x){
int c;while(!isdigit(c=getc())&&c!='-');bool sig=c=='-';
x=sig?0:c-'0';while(isdigit(c=getc()))x=(x<<1)+(x<<3)+c-'0';
if(sig)x=-x;
}
}
#define N 1000010
int h[N];
int q[N],fr,ta,f[N];
int main(){
int n;Fio::Get(n);register int i,j;for(i=1;i<=n;++i)Fio::Get(h[i]);
int Q;Fio::Get(Q);int lim;
while(Q--){
Fio::Get(lim);
fr=ta=0;q[ta++]=1;f[1]=0;
for(i=2;i<=n;++i){
while(fr^ta&&i>q[fr]+lim)++fr;f[i]=f[q[fr]]+(h[q[fr]]<=h[i]);
while(fr^ta&&((f[i]<f[q[ta-1]])||(f[i]==f[q[ta-1]]&&h[i]>h[q[ta-1]])))--ta;
q[ta++]=i;
}
printf("%d\n",f[n]);
}return 0;
}
评论 (0)