[TJOI2013]最长上升子序列

[TJOI2013]最长上升子序列

题面

链接

题解

题目要求在插入数的时候维护最长上升子序列

显然当不维护插入数这一操作时,可以直接DP解决

观察题目,每次插入的数为当前数列最大数

所以此时整个数列最长上升子序列只有两种情况一种是以当前数为结尾,另一种是不为结尾

所以插入数并不会对之前的答案影响

考虑用splay维护,当以当前数为根时,答案不是是以他左子树里的一点为结尾,就是以插入的数为结尾

只需在每个叶节点记录即可

插入时将要插入节点位置旋转到位置X后

只需要先将X转到根,在讲X+1转到根的右儿子,插入到位置X+1的左儿子即可

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 100000 + 10;

inline int read()
{
    int f=1,x=0;
    char ch;
    do
    {
        ch=getchar();
        if(ch=='-') f=-1;
    }while(ch<'0'||ch>'9');
    do
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return f*x;
}

struct Splay
{
    int root;
    int idx;
    int ch[MAXN][2];
    int val[MAXN];
    int fa[MAXN];
    int sz[MAXN];
    int ma[MAXN];
    int dp[MAXN];
    inline int chk(int x)
    {
        return x==ch[fa[x]][1];
    }
    inline void pushup(int x)
    {
        sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
        ma[x]=max(ma[ch[x][0]],max(ma[ch[x][1]],dp[x]));
    }
    inline void rotate(int x)
    {
        int f=fa[x],gf=fa[f];
        int k=chk(x);
        ch[gf][chk(f)]=x;fa[x]=gf;
        ch[f][k]=ch[x][k^1];fa[ch[x][k^1]]=f;
        ch[x][k^1]=f;fa[f]=x;
        pushup(f);pushup(x);
        return;
    }
    inline void splay(int x,int goal)
    {
        while(fa[x]!=goal)
        {
            int f=fa[x],gf=fa[f];
            if(gf!=goal)
            {
                if(chk(x)==chk(f)) rotate(f);
                else rotate(x);
            }
            rotate(x);
        }
        if(!goal) root=x;
    }
    inline void insert(int x)
    {
        int cur=root,f=0;
        while(cur&&val[cur]!=x)
        {
            f=cur;
            if(val[cur]>ch[cur][0]) cur=ch[cur][0];
            else cur=ch[cur][1];
        } 
        cur=++idx;fa[cur]=f;
        if(f) ch[f][x>val[f]]=x;
        sz[cur]=1;
        ch[cur][0]=ch[cur][1]=0;
        val[cur]=x;
        if(!root) root=cur;
        splay(cur,0);
    }
    inline int kth(int k)
    {
        int cur=root;
        while(1)
        {
            if(k<=sz[ch[cur][0]])
            {
                cur=ch[cur][0];
            }
            else if(k==sz[ch[cur][0]]+1) return cur;
            else k-=sz[ch[cur][0]]+1,cur=ch[cur][1];
        }
    }
}tree;

int n;

int main()
{
    n=read();
    tree.insert(n+1);
    tree.insert(0);
    for(int i=1;i<=n;i++)
    {
        int x=read();x++;
        int l=tree.kth(x);
        int r=tree.kth(x+1);
        tree.splay(l,0);
        tree.splay(r,l);
        int t=tree.ch[tree.root][1];
        tree.ch[t][0]=++tree.idx;
        int hhd=tree.ch[t][0];
        tree.fa[tree.ch[t][0]]=t;tree.val[tree.ch[t][0]]=i;
        tree.ch[hhd][0]=tree.ch[hhd][1]=0;
        tree.sz[hhd]=1;tree.splay(hhd,0);
        tree.dp[hhd]=tree.ma[tree.ch[hhd][0]]+1;
        tree.pushup(hhd);
        printf("%d
",tree.ma[hhd]);
    }
}
原文地址:https://www.cnblogs.com/wlzs1432/p/11166854.html