您的位置:首页 > 其它

【线段树+O(nlgn)最长上升子序列】HDU 3564

2012-02-14 16:19 190 查看
the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details这句话要注意插数的时候是插到当前序列里,也就是说不可能插到当前序列末尾,还有,这是可以不连续的!!!我还以为是LICS......囧

#define N 100005
struct node{
int l,r;
int cnt;
}t[N*4];

void build(int l,int r,int id){
t[id].l = l;
t[id].r = r;
t[id].cnt = r-l+1;
if(l == r){
return ;
}
int mid = (l+r)>>1;
build(l,mid,id<<1);
build(mid+1,r,id<<1|1);
}
inline int find_pos(int id,int k){
if(t[id].l == t[id].r)return t[id].l;
if(t[id<<1].cnt<k)return find_pos(id<<1|1,k-t[id<<1].cnt);
else return find_pos(id<<1,k);
}
inline void del(int id,int pos){
t[id].cnt--;
if(t[id].l == t[id].r){
return ;
}
int mid = (t[id].l+t[id].r)>>1;
if(pos<=mid)del(id<<1,pos);
else del(id<<1|1,pos);
}
int a
;
int p
;
int main(){
int ca;
scanf("%d",&ca);
int tt = 1;
while(ca--){
int n;
scanf("%d",&n);
build(1,n,1);
int i,j;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]++;
}
for(i=n;i>=1;i--){
p[i] = find_pos(1,a[i]);
del(1,p[i]);
}
printf("Case #%d:\n",tt++);
memset(a,-1,sizeof(a));
int len = 0;
a[len++]=p[1];//此时的a表示长度为len的序列最后一位的最低位置
printf("1\n");
for(i=2;i<=n;i++){
int tmp = lower_bound(a,a+len,p[i]) - a;
if(a[tmp] == -1){//找不到,证明当前数的位置比前面都大
a[len++] = p[i];
} else if(a[tmp] > p[i]){
a[tmp] = p[i];//长度不变,但是位置要降低
}
printf("%d\n",len);
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: