hdu4521之线段树单点更新

http://acm.hdu.edu.cn/showproblem.php?pid=4521


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<iomanip>
#define INF 99999999
using namespace std;

const int MAX=100000+10;
int sum[MAX<<2];//表示区间内以叶子值结束的最长子序列
int len[MAX];//表示以第i个数结束的最长子序列
int s[MAX];

void Update(int pos,int date,int n,int left,int right){
	if(left == right){sum[n]=date;return;}
	int mid=left+right>>1;
	if(pos<=mid)Update(pos,date,n<<1,left,mid);
	else Update(pos,date,n<<1|1,mid+1,right);
	sum[n]=max(sum[n<<1],sum[n<<1|1]);//更新区间内最长子序列(以某个叶子结束的序列) 
}

int Query(int L,int R,int n,int left,int right){
	if(L<=left && right<=R)return sum[n];
	int mid=left+right>>1,lmax=0,rmax=0;
	if(L<=mid)lmax=Query(L,R,n<<1,left,mid);
	if(R>mid)rmax=Query(L,R,n<<1|1,mid+1,right);
	return max(lmax,rmax);//返回这个区间内的最长子序列 
}

int main(){//O(nlogn)复杂度 
	int n,d;
	while(cin>>n>>d){
		memset(sum,0,sizeof sum);
		int maxlen=0;
		for(int i=1;i<=n;++i){
			scanf("%d",s+i);
			if(i-d-1>0)Update(s[i-d-1],len[i-d-1],1,0,MAX);//更新恰好满足第i个位置的数i-d-1 
			if(s[i]>0)len[i]=Query(0,s[i]-1,1,0,MAX)+1;//查询在s[i]出现之前出现的数且以该数结束的最长子序列 
			else len[i]=1;//在s[i]之前出现的数s[k]一定满足i-k>d,因为插入(更新)的时候是根据i-d-1更新的,i-(k-d-1)=d+1+(i-k)>d
			maxlen=max(maxlen,len[i]);
		}
		cout<<maxlen<<endl;
	}
	return 0;
} 


你可能感兴趣的:(hdu4521之线段树单点更新)