題解 P3572 [POI2014]PTA-Little Bird
阿新 • • 發佈:2020-09-12
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 */