bzoj3173 [Tjoi2013]最长上升子序列 splay

Description


给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?

第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)
N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。

100%的数据 n<=100000

Solution


由于每次插入的数字递增,可知插入数字不影响先前答案
用splay模拟插入得到最终序列,然后倒着删数字记录答案即可
似乎也可以用线段树模拟插入,没写

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

const int INF=0x3f3f3f3f;
const int N=500005;

struct treeNode {
    int son[2],fa,size,num;
} t[N];

int a[N],f[N],s[N];
int ans[N],tot,root;

int read() {
    int x=0,v=1; char ch=getchar();
    for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
    return x*v;
}

void push_up(int now) {
    t[now].size=t[t[now].son[0]].size+t[t[now].son[1]].size+1;
}

void rotate(int x) {
    int y=t[x].fa; int z=t[y].fa;
    int k=t[y].son[1]==x;
    t[z].son[t[z].son[1]==y]=x; t[x].fa=z;
    t[y].son[k]=t[x].son[!k]; t[t[x].son[!k]].fa=y;
    t[y].fa=x; t[x].son[!k]=y;
    push_up(y); push_up(x);
}

void splay(int x,int goal) {
    while (t[x].fa!=goal) {
        int y=t[x].fa; int z=t[y].fa;
        if (z!=goal) {
            if ((t[y].son[1]==x)^(t[z].son[1]==y)) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
    if (!goal) root=x;
}

int kth(int k) {
    int now=root;
    while (233) {
        if (t[t[now].son[0]].size+1==k) return now;
        if (t[t[now].son[0]].size>=k) {
            now=t[now].son[0];
        } else {
            k-=t[t[now].son[0]].size+1;
            now=t[now].son[1];
        }
    }
}

int main(void) {
    freopen("data.in","r",stdin);
    freopen("myp.out","w",stdout);
    int n=read();
    t[1].son[1]=2; t[2].fa=1; t[1].size=2; t[2].size=1;
    tot=2; root=1;
    rep(i,1,n) {
        int k=read();
        int l=kth(k+1),r=kth(k+2);
        splay(l,0); splay(r,l);
        t[r].son[0]=++tot;
        t[tot].fa=r; t[tot].size=1;
        t[tot].num=i;
        push_up(r);
        splay(tot,0);
    }
    rep(i,1,n) s[i]=INF;
    rep(i,1,n) {
        a[i]=kth(i+1);
        a[i]=t[a[i]].num;
        int l=0,r=n,ret=0;
        while (l<=r) {
            int mid=(l+r)>>1;
            if (s[mid]>=a[i]) r=mid-1;
            else l=mid+1,ret=mid;
        }
        f[i]=ret+1;
        s[f[i]]=std:: min(s[f[i]],a[i]);
        ans[a[i]]=f[i];
    }
    rep(i,1,n) {
        ans[i]=std:: max(ans[i],ans[i-1]);
        printf("%d\n", ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/81486785
今日推荐