您的位置:首页 > 产品设计 > UI/UE

ZOJ 3349 Special Subsequence(LIS+线段树优化)

2013-04-20 11:02 369 查看
不难看出状态转移方程opt[i]=max(opt[j])+1(0<=j<i并且|a[j]-a[i] |<=d)

这样的复杂度是n平方,数据量最大10w,明显会TLE,看了网上的题解,可以用线段树来优化

线段树的每个叶子节点表示以i为结尾的最长子串长度,每一次查询之后更新 ans 为

max(ans, query(lower_bound, upper_bound) + 1);这样子就可以比较快的出答案了.

首先要一个数组b保存a数组排序去重复后的内容.然后按照b数组去建树.

然后要查询a[i]的区间只要二分查找一下a[i]-d,a[i]+d在b中的位置[x,y],这样[x,y]就是树的查询范围

连抄带猜写出来的,STL不错

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#include <functional>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=100010;

int segs[maxn<<2],a[maxn],b[maxn],n,d;

void build(int l,int r,int rt){
segs[rt]=0;
if(l==r)return;
int m=(l+r)>>1;
build(lson),build(rson);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return segs[rt];
}
int m=(l+r)>>1,ret=0;
if(L<=m)ret=max(ret,query(L,R,lson));
if(R>m)ret=max(ret,query(L,R,rson));
return ret;
}
void update(int l,int r,int rt,int v,int p){
if(l==r){
segs[rt]=max(v,segs[rt]);
return;
}
int m=(l+r)>>1,ret=0;
if(p<=m)update(lson,v,p);
else if(p>m)update(rson,v,p);
segs[rt]=max(segs[rt<<1],segs[rt<<1|1]);
}
int main(){
while (scanf("%d %d",&n,&d)==2){
for (int i=0;i<n;++i){
scanf("%d",&a[i]);
}
copy(a,a+n,b);
sort(b,b+n);
int bnd=unique(b,b+n)-b,ans=0;
build(0,bnd,1);
for (int i=0;i<n;++i){
int x=query(lower_bound(b,b+bnd,a[i]-d)-b,upper_bound(b,b+bnd,a[i]+d)-b-1,0,bnd,1);
update(0,bnd,1,x+1,lower_bound(b,b+bnd,a[i])-b);
ans=max(x+1,ans);
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: