题解 P3572 [POI2014]PTA-Little Bird

P3572 [POI2014]PTA-Little Bird

首先,这道题的暴力dp非常好写
就是枚举所有能转移到他的点,如果当前枚举到的位置的值大于
当前位置的话,\(f[i]=min(f[i],f[j])\)
否则就\(f[i]=min(f[i],f[j]+1)\)
时间复杂度为O(nk)
考虑优化,因为只是加1或不加,实际上只需要知道能转移到当前节点的位置
的&f&数组最小值即可,同时也要选这个位置数值最大的(想一想为什么)
这样的话,这道题就没了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e6+7;
int n,k,Q;
int f[N],a[N];
int q[N],h1,h2;
int main(){
//	freopen("t4.in","r",stdin);
//	freopen("t4.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
//	memset(f,0x3f,sizeof(f));
	f[1]=0;
	scanf("%d",&Q);
	while(Q--){
		scanf("%d",&k);
		h1=h2=1;
		q[h1]=1;
		for(int i=2;i<=n;i++){
			while(h1<=h2&&i-q[h1]>k) h1++;
			if(a[i]>=a[q[h1]]) f[i]=f[q[h1]]+1;
			else f[i]=f[q[h1]];
			while(h1<=h2&&(f[i]<f[q[h2]]||(f[i]==f[q[h2]]&&a[i]>=a[q[h2]]))) h2--;
			q[++h2]=i;
		}
		cout<<f[n]<<"\n";
	}
	return 0;
}
/*
9
4 6 3 6 3 7 2 6 5 
2
2
5
*/
posted @ 2020-09-12 21:14  Aswert  阅读(170)  评论(0编辑  收藏  举报