版权声明:2333 https://blog.csdn.net/liangzihao1/article/details/81914013
题目描述
给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?
输入输出格式
输入格式:
第一行一个整数
,表示我们要将
到
插入序列中。
接下是
个数字,第
个数字
,表示我们将
插入到位置
输出格式:
行,第
行表示
插入
位置后序列的最长上升子序列的长度是多少。
输入输出样例
输入样例#1:
3
0 0 2
输出样例#1:
1
1
2
说明
100%的数据
分析:
插入应该就能想到用平衡树了。我们以数组下标建平衡树。
插入一个数到
,可以先把插入前排名
的点
旋到根,再把排名
的点
旋到根,那么这个数可以插入到
的右儿子。
设子序列长为
,
因为升序插入,更新当前点的最长不下降子序列可以把当前点旋到根,给他的左儿子的
取一个
给当前点。答案就是整棵树的
的
。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
const int maxn=1e5+7;
using namespace std;
int n,x,root,ans;
struct node{
int fa,l,r,maxx,size,data;
}t[maxn];
void updata(int x)
{
t[x].size=t[t[x].l].size+t[t[x].r].size+1;
t[x].maxx=max(t[t[x].l].maxx,t[t[x].r].maxx);
t[x].maxx=max(t[x].maxx,t[x].data);
}
void rttr(int x)
{
int y=t[x].l;
t[x].l=t[y].r;
if (t[y].r) t[t[y].r].fa=x;
if (t[t[x].fa].l==x) t[t[x].fa].l=y;
else if (t[t[x].fa].r==x) t[t[x].fa].r=y;
t[y].fa=t[x].fa;
t[x].fa=y;
t[y].r=x;
updata(x); updata(y);
}
void rttl(int x)
{
int y=t[x].r;
t[x].r=t[y].l;
if (t[y].l) t[t[y].l].fa=x;
if (t[t[x].fa].l==x) t[t[x].fa].l=y;
else if (t[t[x].fa].r==x) t[t[x].fa].r=y;
t[y].fa=t[x].fa;
t[x].fa=y;
t[y].l=x;
updata(x); updata(y);
}
bool isroot(int x)
{
return t[x].fa==0;
}
void splay(int x)
{
while (!isroot(x))
{
int p=t[x].fa,g=t[p].fa;
if (isroot(p))
{
if (t[p].l==x) rttr(p);
else rttl(p);
}
else
{
if (t[p].l==x)
{
if (t[g].l==p) rttr(p),rttr(g);
else rttr(p),rttl(g);
}
else
{
if (t[g].l==p) rttl(p),rttr(g);
else rttl(p),rttl(g);
}
}
}
}
int find(int x,int k)
{
if ((!k) || (t[x].size<k)) return 0;
int size=t[t[x].l].size;
if (size==k-1) return x;
if (k<=size) return find(t[x].l,k);
else return find(t[x].r,k-size-1);
}
int main()
{
scanf("%d",&n);
scanf("%d",&x);
ans=1;
t[1].data=1;
t[1].maxx=1;
t[1].size=1;
root=1;
printf("%d\n",ans);
for (int i=2;i<=n;i++)
{
scanf("%d",&x);
int d=find(root,x),f=find(root,x+1);
if (d) splay(d),root=d;
if (f) splay(f),root=f;
if (!d) t[f].l=i,t[i].fa=f;
else
{
if (!f) t[d].r=i,t[i].fa=d;
else t[d].r=i,t[i].fa=d;
}
splay(i);
root=i;
t[i].data=t[t[i].l].maxx+1;
updata(i);
ans=max(ans,t[i].maxx);
printf("%d\n",ans);
}
}