您的位置:首页 > 其它

HDU 4521-小明序列(线段树好题)

2015-08-09 22:16 337 查看
题意:

n个数字的序列,求各数位置间隔大于d的最长上升子序列

分析:

最基本的dp但是数据量大O(n^2)肯定超时 前dp[i]为的最长上升子序列是由前dp[1]---dp[i-d-1]符合条件的最大值得到,我们可以用线段树维护dp[1]---dp[i-d-1]的最大值

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<1|1
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
#define N 100010
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
int maxv[N*4],a
,dp
;
void pushup(int rt){
maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
void build(int l,int r,int rt){
maxv[rt]=0;
if(l==r){
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int pos,int num,int l,int r,int rt){
if(l==r){
maxv[rt]=max(maxv[rt],num);
return;
}
int m=(l+r)>>1;
if(pos<=m)update(pos,num,lson);
else update(pos,num,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r){
return maxv[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;
while(~scanf("%d%d",&n,&d)){
int maxl=0;
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
maxl=max(maxl,a[i]);
}
memset(dp,0,sizeof(dp));
build(0,maxl,1);//以数值做区间
int maxans=0;
for(int i=1;i<=n;++i){
if(i-d-1>0){
update(a[i-d-1],dp[i-d-1],0,maxl,1);//更新点
}
if(a[i]==0){
dp[i]=1;
}
else
dp[i]=query(0,a[i]-1,0,maxl,1)+1;//查的恰好是值<a[i]且dp[1]---dp[i-d-1]的最大值
maxans=max(maxans,dp[i]);
}
printf("%d\n",maxans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: