題目鏈接: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;
}