1. 程式人生 > 實用技巧 >題解 P3572 [POI2014]PTA-Little Bird

題解 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
*/