最长上升子序列
作者:互联网
挺水一题。
由于不强制在线,可以把所有操作读入之后,把最后的数组处理出来了再考虑答案(主要是平衡树动态维护LIS一时没想到怎么做)。显然有结论,第i次的答案可以看成是最后数组剔除掉所有大于i的数剩下的序列的LIS,而所有大于i的数是不会被小于等于i的数吸纳的,所以第i次的答案相当于是最后数组上所有以小于等于i的元素结尾的LIS的最大值,树状数组线性(似乎不能这么说?)求完每个数的值之后求一个值域的前缀最大值即可。前面构造部分用平衡树(也有大神用vector过的,而且跑得飞快?),而且是非常基础的平衡树维护序列。
代码很好写,二千字。
#include<bits/stdc++.h>
//#define zczc
const int N=100010;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline int max(int s1,int s2){
return s1<s2?s2:s1;
}
int m,n;
#define lc t[x].ch[0]
#define rc t[x].ch[1]
struct node{
int f,ch[2],data,size;
}t[N];
int cnt,root;
inline void pushup(int x){
t[x].size=t[lc].size+t[rc].size+1;
}
inline void rotate(int x){
int y=t[x].f;int z=t[y].f;
int kk=t[y].ch[1]==x;int cd=t[x].ch[kk^1];
if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].f=z;
t[cd].f=y;t[y].ch[kk]=cd;
t[x].ch[kk^1]=y;t[y].f=x;
pushup(y);pushup(x);
}
inline void splay(int x,int rt){
while(t[x].f^rt){
int y=t[x].f;int z=t[y].f;
if(z^rt)(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
rotate(x);
}
if(rt==0)root=x;
}
inline int find(int x,int kk){
if(t[lc].size>=kk)return find(lc,kk);
if(t[lc].size+1==kk)return x;
return find(rc,kk-t[lc].size-1);
}
inline void insert(int pl,int val){
//printf("%d %d\n",pl,val);
int s1=find(root,pl),s2=find(root,pl+1);
splay(s1,0);splay(s2,root);
t[s2].ch[0]=++cnt;
t[cnt].data=val;t[cnt].size=1;t[cnt].f=s2;
pushup(s2);pushup(s1);
return;
}
int a[N],top=-1;
void dfs(int x){
if(!x)return;
dfs(lc);
a[++top]=t[x].data;
dfs(rc);
}
void print(int x){
if(!x)return;
printf("%d %d %d&%d %d\n",x,t[x].data,lc,rc,t[x].f);
print(lc);print(rc);
}
#undef lc
#undef rc
#define lowbit (wh&-wh)
int c[N];
inline void change(int wh,int val){
for(;wh<=m;wh+=lowbit)c[wh]=max(c[wh],val);
}
inline int work(int wh){
int an=0;
for(;wh;wh-=lowbit)an=max(an,c[wh]);
return an;
}
#undef lowbit
int an[N];
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
srand(time(0));
root=1;cnt=2;
t[1].ch[1]=2;t[1].size=2;
t[2].size=1;t[2].f=1;
read(m);
for(int i=1;i<=m;i++){
read(n);insert(n+1,i);
//print(root);printf("\n");
splay(rand()%cnt+1,0);
}
dfs(root);
//for(int i=1;i<=m;i++)printf("%d ",a[i]);
for(int i=1;i<=m;i++){
an[a[i]]=work(a[i])+1;
change(a[i],an[a[i]]);
}
int ans=0;
for(int i=1;i<=m;i++)printf("%d\n",ans=max(ans,an[i]));
return 0;
}
标签:return,lc,int,s2,void,wh,序列,上升,最长 来源: https://www.cnblogs.com/dai-se-can-tian/p/16438003.html