其他分享
首页 > 其他分享> > 最长上升子序列

最长上升子序列

作者:互联网

link

挺水一题。

由于不强制在线,可以把所有操作读入之后,把最后的数组处理出来了再考虑答案(主要是平衡树动态维护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