题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1950
题意:实际就是求最长递增子序列
题解:有两种解法,一种是利用二分,一种是用线段树
这个是这题的二分代码:
1 #include <cstdio> 2 #include<algorithm> 3 #define F(i,a,b) for(int i=a;i<=b;i++) 4 using namespace std; 5 const int N = 1e5+7; 6 int a[N],d[N]; 7 int LIS(int* a, int n, int* d){ 8 int len=1;d[1]=a[1]; 9 F(i,2,n)if(d[len]<a[i])d[++len]=a[i]; 10 else d[lower_bound(d+1,d+1+len,a[i])-d]=a[i]; 11 return len; 12 } 13 int main(){ 14 int t,n; 15 scanf("%d",&t); 16 while(t--){ 17 scanf("%d",&n); 18 for(int i =1; i <=n; i++)scanf("%d",&a[i]); 19 printf("%d ",LIS(a,n,d)); 20 } 21 return 0; 22 } 23 这个是求LIS的线段树的代码 24 25 #include<cstdio> 26 #include<algorithm> 27 #define root 1,n,1 28 #define ls l,m,rt<<1 29 #define rs m+1,r,rt<<1|1 30 #define F(i,a,b) for(int i=a;i<=b;i++) 31 using namespace std; 32 const int N=1e5+7; 33 int n,sum[N<<2],a[N],ans,dp[N]; 34 35 void update(int x,int k,int l,int r,int rt){ 36 if(l==r){sum[rt]=k;return;} 37 int m=(l+r)>>1; 38 if(x<=m)update(x,k,ls); 39 else update(x,k,rs); 40 sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); 41 } 42 43 int query(int L,int R,int l,int r,int rt){ 44 if(L<=l&&r<=R)return sum[rt]; 45 int m=(l+r)>>1,ret=0; 46 if(L<=m)ret=max(ret,query(L,R,ls)); 47 if(m<R)ret=max(ret,query(L,R,rs)); 48 return ret; 49 } 50 51 int main(){ 52 while(~scanf("%d",&n)){ 53 F(i,1,n)scanf("%d",a+i),dp[i]=0; 54 F(i,0,(N<<2)-1)sum[i]=0;ans=0; 55 F(i,1,n){ 56 if(a[i]-1>0){ 57 dp[i]=max(dp[i],query(1,a[i]-1,root))+1; 58 update(a[i],dp[i],root); 59 }else dp[i]=1,update(a[i],dp[i],root); 60 ans=max(dp[i],ans); 61 } 62 printf("%d ",ans); 63 } 64 return 0; 65 }