您的位置:首页 > 其它

[ DP ] [ POI2007 ] BZOJ1109

2018-01-25 19:05 357 查看
先考虑 O(n2)O(n2) 的DP:

令 fifi 为使 ii 满足条件时前 ii 个数的答案。可以得到转移方程:

fi=max{fj+1 | j<i,aj<ai,ai−aj≤i−j}fi=max{fj+1 | j<i,aj<ai,ai−aj≤i−j}

发现通过后 22 个条件可以推出第一个条件。那么按照 i−aii−ai 排序然后求一遍最长上升子序列就好了。

#include<bits/stdc++.h>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
#define fi first
#define se second
typedef pair<int,int> abcd;
const int N=100010;
int k,n,m,x;
int c
,Ans;
abcd a
;
inline int Find(int x){
int l=1,r=n-1,Ans=0;
while(l<=r){
int Mid=l+r>>1;
if(c[Mid]<x)Ans=Mid,l=Mid+1;else r=Mid-1;
}
return Ans;
}
int main(){
Read(n);
int cnt=0;
for(int i=1;i<=n;i++){
Read(x);
if(i>=x)a[++cnt]=abcd(i-x,x);
}
n=cnt;
sort(a+1,a+n+1);
memset(c,127,sizeof(c));
for(int i=1;i<=n;i++){
x=Find(a[i].se)+1;
c[x]=min(c[x],a[i].se);
Ans=max(Ans,x);
}
cout<<Ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: