BZOJ 3173 最长上升子序列

Posted on 2017-03-13 15:27  ziliuziliu  阅读(151)  评论(0编辑  收藏  举报

直接用一颗splay维护这个序列。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100050
using namespace std;
int n,x,size[maxn],fath[maxn],tree[maxn][3],mx[maxn],f[maxn],root,tot=0;
void reset()
{
    root=1;tot=2;tree[1][2]=2;fath[2]=1;
    mx[1]=mx[2]=0;size[1]=2;size[2]=1;
}
void pushup(int x)
{
    size[x]=size[tree[x][1]]+size[tree[x][2]]+1;
    mx[x]=max(f[x],max(mx[tree[x][1]],mx[tree[x][2]]));
}
int find_kth(int now,int k)
{
    if (tree[now][1]==0 && tree[now][2]==0) return now;
    int r=size[tree[now][1]];
    if (k<=r) return find_kth(tree[now][1],k);
    else if (r+1==k) return now;
    else return find_kth(tree[now][2],k-r-1);
}
void rotate(int x,int &k)
{
    int y=fath[x],z=fath[y],l,r;
    if (tree[y][1]==x) l=1;else l=2;r=3-l;
    if (y==k) k=x;
    else
    {
        if (tree[z][1]==y) tree[z][1]=x;
        else tree[z][2]=x;
    }
    fath[x]=z;fath[y]=x;fath[tree[x][r]]=y;
    tree[y][l]=tree[x][r];tree[x][r]=y;
    pushup(y);pushup(x);
}
void splay(int x,int &k)
{
    while (x!=k)
    {
        int y=fath[x],z=fath[y];
        if (y!=k)
        {
            if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void insert(int x,int y,int z)
{
    fath[y]=z;fath[z]=x;tree[z][1]=y;tree[x][1]=z;
    pushup(z);pushup(x);splay(y,root);
}
int main()
{
    scanf("%d",&n);
    reset();
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        int pos=find_kth(root,x+2);
        splay(pos,root);
        pos=find_kth(root,x+1);
        splay(pos,tree[root][1]);
        f[i+2]=mx[tree[root][1]]+1;
        insert(root,pos,i+2);
        printf("%d\n",mx[root]);
    }
    return 0;
}