zoj 3349 简单DP 线段树或树状数组优化

已经做过一个类似的题目了,只是这道题目求的是最长的长度,那个题目求的是总的这样的序列的个数,都是用线段树或者树状数组来优化求和操作,使之降为log(n)

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 100010;
int sum[maxn<<2];
int num[maxn];
int a[maxn];
int dp[maxn];
int max(int a,int b){
return a>b?a:b;
}
void pushup(int rt){
sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}
void build(int l,int r,int rt){
if(l==r) {
sum[rt]=0;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int p,int val,int l,int r,int rt){
if(l==r){
sum[rt]=val;
return ;
}
int m=(l+r)>>1;
if(p<=m) update(p,val,lson);
else update(p,val,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return sum[rt];
}
int m=(l+r)>>1;
int ans=0;
if(L<=m) ans=max(ans,query(L,R,lson));
if(R>m) ans=max(ans,query(L,R,rson));
return ans;
}
int main()
{
int n,d,i,j;
while(scanf("%d%d",&n,&d)!=EOF){
for(i=1;i<=n;i++) {
dp[1]=1;
scanf("%d",&num[i]);
a[i]=num[i];
}
build(1,n,1);
sort(a+1,a+n+1);
int tot=unique(a+1,a+n+1)-(a+1);
for(i=1;i<=n;i++){
int id=lower_bound(a+1,a+tot+1,num[i])-a;
int l=lower_bound(a+1,a+tot+1,num[i]-d)-a;
int r=upper_bound(a+1,a+tot+1,num[i]+d)-a-1;
dp[i]=query(l,r,1,n,1)+1;
update(id,dp[i],1,n,1);
}
int ans=0;
for(i=1;i<=n;i++)
if(dp[i]>ans) ans=dp[i];
printf("%d\n",ans);
}
return 0;
}



你可能感兴趣的:(树状数组)