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

(1)插入元素;求最长上升子序列。

他人具体代码:

View Code
#include<stdio.h>
#include<string.h>
#define lowbit(i) (i&(-i))
const int MAXN=100005;
const int MAXLOG=17;
int B[MAXN],pos[MAXN];
int N;
void update(int i,int value){   //维护空位的个数
    for(;i<=N;i+=lowbit(i))   
        B[i]+=value;    
} 
int getK(int k){//返回第k个空位的下标
    int ans=0;
    for(int i=MAXLOG;i>=0;i--)
    {
        ans+=(1<<i);
        if(ans>N||B[ans]>=k)
            ans-=(1<<i);
        else k-=B[ans];
    }
    return ans+1;
}
void updateM(int i, int value)//维护LIS的长度
{
    for(;i<=N;i+=lowbit(i))
        if(value>B[i])
            B[i]=value;
} 
int getM(int i){//i代表位置,往前找最大的长度,i位置的数肯定可以使长度加1
    int ans=0;
    for (;i>0;i-=lowbit(i))
        if(B[i]>ans)ans=B[i];
        return ans;
}
int main()
{
    int t;
    int i,j,k,g=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&N);
        memset(B,0,sizeof(int)*(N+1));
        for(i=1;i<=N;i++)
        {
            scanf("%d",&pos[i]);
            update(i,1);
        }//初始时有n个空位,从后往前插入
        for(i=N;i>=1;i--)
        {
            pos[i]=getK(pos[i]+1);//第pos[i]+1个空位的位置
            update(pos[i],-1);
        }
        int ans=0;
        printf("Case #%d:\n",g++);
        memset(B,0,sizeof(int)*(N+1));
        for(i=1;i<=N;i++)
        {
            int len=getM(pos[i]);
            if(len+1>ans)ans=len+1; 
            printf("%d\n",ans);
            updateM(pos[i],len+1);
        }puts("");
    }
    return 0;
}