P3287 [SCOI2014]方伯伯的玉米田
阿新 • • 發佈:2020-09-06
首先可以證明,一定存在一種最優解,每次選擇的區間結尾都是 \(n\)。因為如果某一個區間結尾不是 \(n\),將其替換成 \(n\) 仍然保持單調不下降。接著都按這個策略拔高玉米。
令 \(f_{i,j}\) 表示 \(1\sim i\) 這段字首進行了 \(j\) 次操作,第 \(i\) 株玉米不被拔掉,所能剩下最多的玉米。
\[f_{i,j}=\max\{f_{p,q}|p<i,q\leq j,a_p+q\leq a_i+j\}+1 \]
列舉 \(i\),剩下兩個限制用二維樹狀陣列維護即可。
有一個小細節,操作次數可能為 \(0\),扔進樹狀陣列時需要加 \(1\)。
時間複雜度 \(O(nk\log k\log a)\)
code:
#include<bits/stdc++.h> using namespace std; #define Max(x,y)((x)>(y)?x:y) #define For(i,x,y)for(i=x;i<=(y);i++) #define Down(i,x,y)for(i=x;i>=(y);i--) #define lowbit(x)((x)&-(x)) int c[505][5505],a[10005],k,mx; int sum(int x,int tmp) { int y,res=0; while(x) { y=tmp; while(y)res=Max(c[x][y],res),y-=lowbit(y); x-=lowbit(x); } return res; } void add(int x,int tmp,int z) { int y; while(x<=k+1) { y=tmp; while(y<=mx+k)c[x][y]=Max(c[x][y],z),y+=lowbit(y); x+=lowbit(x); } } int main() { int n,i,j,tot,ans=0; scanf("%d%d",&n,&k); For(i,1,n)scanf("%d",&a[i]),mx=Max(mx,a[i]); For(i,1,n) Down(j,k,0) { tot=sum(j+1,a[i]+j)+1; add(j+1,a[i]+j,tot); ans=Max(ans,tot); } printf("%d",ans); return 0; }