1. 程式人生 > 其它 >「BZOJ3594」方伯伯的玉米田 題解 (資料結構優化DP)

「BZOJ3594」方伯伯的玉米田 題解 (資料結構優化DP)

題目簡介

題目描述

方伯伯在自己的農田邊散步,他突然發現田裡的一排玉米非常的不美。 這排玉米一共有 \(N\) 株,它們的高度參差不齊。 方伯伯認為單調不下降序列很美,所以他決定先把一些玉米拔高,再把破壞美感的玉米拔除掉,使得剩下的玉米的高度構成一個單調不下降序列。 方伯伯可以選擇一個區間,把這個區間的玉米全部拔高 \(1\) 單位高度,他可以進行最多 \(K\) 次這樣的操作。拔玉米則可以隨意選擇一個集合的玉米拔掉。 問能最多剩多少株玉米,來構成一排美麗的玉米。

輸入

\(1\) 行包含 \(2\) 個整數 \(n\)\(K\),分別表示這排玉米的數目以及最多可進行多少次操作。 第 \(2\)

行包含 \(n\) 個整數,第 \(i\) 個數表示這排玉米,從左到右第 \(i\) 株玉米的高度 \(a_i\)

輸出

輸出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) \]

由於資料量巨大,使用二維樹狀陣列

\(c\)來表示\(f\)

程式碼

#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;
}

$$-----END-----$$