解题思路
因为是1~n顺序插入,所以新插入元素不会对之前已经求出的值产生影响。以新插入元素为结尾的最长上升子序列为它插入位置之前所有元素的maxx加1。用平衡树维护,支持插入和查询。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<string>
using namespace std;
struct node{
int mx,yx,siz,key;
node* ch[2];
}*root=NULL;
int n,ans,rans,xk;
void Rotate(node* &p,bool f){
node *t=p->ch[f^1];
p->ch[f^1]=t->ch[f];
t->ch[f]=p;
p->siz=1;p->mx=p->key;
if(p->ch[0]!=NULL) {p->siz+=p->ch[0]->siz;p->mx=max(p->mx,p->ch[0]->mx);}
if(p->ch[1]!=NULL) {p->siz+=p->ch[1]->siz;p->mx=max(p->mx,p->ch[1]->mx);}
t->siz=1;t->mx=t->key;
if(t->ch[0]!=NULL) {t->siz+=t->ch[0]->siz;t->mx=max(t->mx,t->ch[0]->mx);}
if(t->ch[1]!=NULL) {t->siz+=t->ch[1]->siz;t->mx=max(t->mx,t->ch[1]->mx);}
p=t;
}
void ch(node* &p,int sum){
int s=0;
if(p==NULL || sum==0) return ;
if(p->ch[0]!=NULL) s+=p->ch[0]->siz;
if(sum>s) {
if(p->ch[0]!=NULL) rans=max(rans,p->ch[0]->mx);
rans=max(rans,p->key);
ch(p->ch[1],sum-s-1);
}
else if(sum<s) ch(p->ch[0],sum);
else rans=max(rans,p->ch[0]->mx);
}
void Insert(node* &p,int sum){
if(p==NULL) {
p=new node;
p->mx=p->key=rans;
p->siz=1;p->yx=rand();
return ;
}
int s=0;
if(p->ch[0]!=NULL) s+=p->ch[0]->siz;
if(sum<=s) {
Insert(p->ch[0],sum);
if(p->yx>p->ch[0]->yx) Rotate(p,1);
else {
p->siz++;
p->mx=max(p->mx,p->ch[0]->mx);
}
}
else {
Insert(p->ch[1],sum-s-1);
if(p->yx>p->ch[1]->yx) Rotate(p,0);
else {
p->siz++;
p->mx=max(p->mx,p->ch[1]->mx);
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&xk);
rans=0;ch(root,xk);
rans++;ans=max(rans,ans);
Insert(root,xk);printf("%d\n",ans);
}
return 0;
}