HDU 3564 線段樹+LIS


題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3564


題意:給出n個數,串初始爲空,Xk表示把k插入到當前串的Xk位置,求每插入一個數後的最長遞增子序列的長度

分析:現根據X求出最終每個數的位置 ,求位置數組的LIS即爲數的LIS

從後往前遍歷X數組,找到第Xk個空着的位置即爲K的最終位置,線段樹求解



#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 100005
using namespace std;
int sum[N<<2],a[N],cnt=0,tmp[N];
void pushup(int rt){
   sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int x,int c,int l,int r,int rt){
    if(l==r){
        a[x]=r;
        sum[rt]=0;
        return ;
    }
    int m=(l+r)>>1;
    if(c<=sum[rt<<1])
    update(x,c,lson);
    else
    update(x,c-sum[rt<<1],rson);
    pushup(rt);
}
void build(int l,int r,int rt){
    if(l==r){
        sum[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void solve(int n){
    vector<int> v;
   int  Max=0;
    for(int i=1;i<=n;i++){
        int u=upper_bound(v.begin(),v.end(),a[i])-v.begin();
        if(u+1>Max)
        Max=u+1;
        if(u==v.size())
        v.push_back(a[i]);
        else
        v[u]=a[i];
        printf("%d\n",Max);
    }
}
int main()
{
    int T,n,ics;
    scanf("%d",&T);
    for(ics=1;ics<=T;ics++){
        scanf("%d",&n);
        build(1,n,1);
        for(int i=1;i<=n;i++){
            scanf("%d",&tmp[i]);
        }
        for(int i=n;i>=1;i--)
        update(i,tmp[i]+1,1,n,1);
        printf("Case #%d:\n",ics);
        solve(n);
        printf("\n");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章