首页 > 代码库 > BZOJ 3173 Tjoi2013 最长上升子序列 Treap+树状数组

BZOJ 3173 Tjoi2013 最长上升子序列 Treap+树状数组

题目大意:给定一个序列,依次将1~n插入,问每次插入之后序列的LIS长度是多少

由于是从小到大插入,因此插入一个数之后显然是不影响之前的答案的

因此我们不妨先用平衡树搞出插入之后的序列,再求一遍LIS即可

注意最后每个点还要对前面的取一下max 因为插入后LIS可能还是之前的序列

蒟蒻的我到底还是把平衡树写挂了。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n,a[M],ans[M];
namespace Treap{
	struct abcd{
		abcd *ls,*rs;
		int val,key,size;
		abcd(int x);
		void Maintain();
	}*null=new abcd(0),*root=null;
	abcd :: abcd(int x)
	{
		ls=rs=null;
		val=x;
		key=rand()*(bool)x;
		size=(bool)x;
	}
	void abcd :: Maintain()
	{
		size=ls->size+rs->size+1;
	}
	void Zig(abcd *&x)
	{
		abcd *y=x->ls;
		x->ls=y->rs;
		y->rs=x;
		x=y;
		x->rs->Maintain();
	}
	void Zag(abcd *&x)
	{
		abcd *y=x->rs;
		x->rs=y->ls;
		y->ls=x;
		x=y;
		x->ls->Maintain();
	}
	void Insert(abcd *&x,int y,int z)
	{
		if(x==null)
		{
			x=new abcd(z);
			return ;
		}
		if(y<=x->ls->size)
		{
			Insert(x->ls,y,z);
			if(x->ls->key>x->key)
				Zig(x);
		}
		else
		{
			Insert(x->rs,y-x->ls->size-1,z);
			if(x->rs->key>x->key)
				Zag(x);
		}
		x->Maintain();
	}
	void Output(abcd *x)
	{
		static int cnt;
		if(x==null)
			return ;
		Output(x->ls);
		a[++cnt]=x->val;
		Output(x->rs);
	}
}
namespace BIT{
	int c[M];
	void Update(int x,int y)
	{
		for(;x<=n;x+=x&-x)
			c[x]=max(c[x],y);
	}
	int Get_Ans(int x)
	{
		int re=0;
		for(;x;x-=x&-x)
			re=max(re,c[x]);
		return re;
	}
}
int main()
{
	using namespace Treap;
	using namespace BIT;
	int i,x;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		scanf("%d",&x);
		Insert(root,x,i);
	}
	Output(root);
	for(i=1;i<=n;i++)
	{
		int temp=Get_Ans(a[i])+1;
		Update(a[i],temp);
		ans[a[i]]=temp;
	}
	for(i=1;i<=n;i++)
		ans[i]=max(ans[i],ans[i-1]);
	for(i=1;i<=n;i++)
		printf("%d\n",ans[i]);
	return 0;
}


BZOJ 3173 Tjoi2013 最长上升子序列 Treap+树状数组