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

题目传送门

题目分析:

DP,设 f [ i ] f[i] f[i]表示答案序列以第i个点结尾的最长长度, a [ i ] a[i] a[i]为第i个点的数。
那么当 i ≥ a [ i ] i\ge a[i] ia[i]时,有 f [ i ] = f [ j ] + 1 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]ij>=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] a[i]a[j]ia[i]ja[j],可以看出,这样的转移已经保证了 i ≥ j i\ge j ij,那么只需要按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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值