「BZOJ3594」方伯伯的玉米田 題解 (資料結構優化DP)
阿新 • • 發佈:2021-10-18
題目簡介
題目描述
方伯伯在自己的農田邊散步,他突然發現田裡的一排玉米非常的不美。 這排玉米一共有 \(N\) 株,它們的高度參差不齊。 方伯伯認為單調不下降序列很美,所以他決定先把一些玉米拔高,再把破壞美感的玉米拔除掉,使得剩下的玉米的高度構成一個單調不下降序列。 方伯伯可以選擇一個區間,把這個區間的玉米全部拔高 \(1\) 單位高度,他可以進行最多 \(K\) 次這樣的操作。拔玉米則可以隨意選擇一個集合的玉米拔掉。 問能最多剩多少株玉米,來構成一排美麗的玉米。
輸入
第 \(1\) 行包含 \(2\) 個整數 \(n\),\(K\),分別表示這排玉米的數目以及最多可進行多少次操作。 第 \(2\)
輸出
輸出1個整數,最多剩下的玉米數。
樣例輸入
3 1
2 1 3
樣例輸出
3
提示
\(1<N<10000,1<K≤500,1\leq a_i\leq 5000\)
分析
題目中有兩個要素,一是被拔高的位置,二是被拔高的次數。
由此,考慮設定二元DP陣列\(f_{i,j}\)來表示前 \(i\) 個位置,被拔高了 \(j\) 次時的最長不下降子序列長度。
可以得到狀態轉移方程:
\[f_{i,j}=max\{f_{x,y}\} +1 (x\leq i,a_x+y\leq a_i+j) \]由於資料量巨大,使用二維樹狀陣列
程式碼
#include<bits/stdc++.h> const int maxn=10010; int n,k; int m; int a[maxn]; int c[maxn][510]; inline int mymax(int fir,int sec){return fir>sec?fir:sec;} inline int lowbit(int x){return x&(-x);} inline void modifit(int x,int y,int dis){ for(int i=x;i<=m+k;i+=lowbit(i)) for(int j=y;j<=k+1;j+=lowbit(j)) c[i][j]=mymax(c[i][j],dis); } inline int query(int x,int y){ int res=0; for(int i=x;i;i-=lowbit(i)) for(int j=y;j;j-=lowbit(j)) res=mymax(res,c[i][j]); return res; } int ans; int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]),m=mymax(m,a[i]); for(int i=1;i<=n;i++) for(int j=k;j>=0;j--){ int res=query(a[i]+j,j+1)+1; ans=mymax(ans,res); modifit(a[i]+j,j+1,res); } printf("%d",ans); return 0; }