BZOJ 1109: [POI2007]堆积木Klo 【DP优化】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88900002

题目传送门

题目分析:

DP,设 f [ i ] f[i] 表示答案序列以第i个点结尾的最长长度, a [ i ] a[i] 为第i个点的数。
那么当 i a [ i ] i\ge a[i] 时,有 f [ i ] = f [ j ] + 1 f[i]=f[j]+1 ,这个转移需要满足 a [ i ] a [ j ] i j > = a [ i ] a [ j ] a[i]\ge a[j]且i-j>=a[i]-a[j]
移一下项就是 a [ i ] a [ j ] i a [ i ] j a [ j ] a[i]\ge a[j]且i-a[i]\ge j-a[j] ,可以看出,这样的转移已经保证了 i j i\ge j ,那么只需要按a[i]排序,把i-a[i]放进树状数组里面,每次找最大值即可。

Code:

#include<cstdio>
#include<cctype>
#include<algorithm>
#define maxn 100005
char cb[1<<15],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
	char c;while(!isdigit(c=getc()));
	for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
using namespace std;
int n,ans;
struct node{
	int x,id;
	bool operator < (const node &p)const{return x==p.x?id>p.id:x<p.x;}
}a[maxn];
int arr[maxn];
void upd(int i,int d){for(;i<=n;i+=i&-i) arr[i]=max(arr[i],d);}
int qmax(int i){int s=0;for(;i;i-=i&-i) s=max(s,arr[i]);return s;}
int main()
{
	read(n);
	for(int i=1;i<=n;i++) read(a[i].x),a[i].id=i;
	sort(a+1,a+1+n);
	for(int i=1,x;i<=n;i++) if(a[i].id>=a[i].x) ans=max(ans,x=qmax(a[i].id-a[i].x+1)+1),upd(a[i].id-a[i].x+1,x);
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/88900002