• BZOJ3173:[TJOI2013]最长上升子序列(Splay)


    Description

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

    Input

    第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)

    Output

    N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。

    Sample Input

    3
    0 0 2

    Sample Output

    1
    1
    2

    HINT

    100%的数据 n<=100000

    Solution

    设$f[i]$表示以$i$数字为结尾的最长上升子序列长度。

    可以发现插入一个数的时候只有当前这个数的$f$会变化,也就是当前这个数前面一段的$max(f)+1$。

    用$Splay$维护一下就好了。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define N (100009)
     5 using namespace std;
     6 
     7 int n,m,p,ans,Root;
     8 int Father[N],Son[N][2],f[N],Max[N],Size[N];
     9 
    10 inline int read()
    11 {
    12     int x=0,w=1; char c=getchar();
    13     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
    14     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
    15     return x*w;
    16 }
    17 
    18 int Get(int x)
    19 {
    20     return Son[Father[x]][1]==x;
    21 }
    22 
    23 void Pushup(int x)
    24 {
    25     Max[x]=f[x];
    26     if (Son[x][0]) Max[x]=max(Max[x],Max[Son[x][0]]);
    27     if (Son[x][1]) Max[x]=max(Max[x],Max[Son[x][1]]);
    28     Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;
    29 }
    30 
    31 void Rotate(int x)
    32 {
    33     int wh=Get(x);
    34     int fa=Father[x],fafa=Father[fa];
    35     if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
    36     Father[fa]=x; Son[fa][wh]=Son[x][wh^1];
    37     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
    38     Father[x]=fafa; Son[x][wh^1]=fa;
    39     Pushup(fa); Pushup(x);
    40 }
    41 
    42 void Splay(int x,int tar)
    43 {
    44     for (int fa; (fa=Father[x])!=tar; Rotate(x))
    45         if (Father[fa]!=tar) Rotate(Get(fa)==Get(x)?fa:x);
    46     if (!tar) Root=x;
    47 }
    48 
    49 int Next(int now)
    50 {
    51     if (!Son[now][1]) return now;
    52     now=Son[now][1];
    53     while (Son[now][0]) now=Son[now][0];
    54     return now;
    55 }
    56 
    57 int Findkth(int x)
    58 {
    59     int now=Root;
    60     while (1)
    61         if (x<=Size[Son[now][0]]) now=Son[now][0];
    62         else
    63         {
    64             x-=Size[Son[now][0]];
    65             if (x==1) {Splay(now,0); return now;}
    66             x--; now=Son[now][1];
    67         }
    68 }
    69 
    70 int main()
    71 {
    72     n=read();
    73     Max[1]=Max[n+2]=f[1]=f[n+2]=-2e9;
    74     Father[n+2]=1; Son[1][1]=n+2;
    75     for (int i=2; i<=n+2; ++i) Size[i]=1;
    76     Size[1]=2; Root=1;
    77     for (int i=2; i<=n+1; ++i)
    78     {
    79         p=read(); p=Findkth(p+1);
    80         int nxt=Next(Root);
    81         
    82         Splay(1,0);
    83         if (nxt!=1) Splay(nxt,1);
    84         f[i]=Max[Son[nxt][0]]+1;
    85         ans=max(ans,f[i]);
    86         printf("%d
    ",ans);
    87         
    88         Splay(p,0);
    89         if (nxt!=p) Splay(nxt,p);
    90         Father[i]=nxt; Son[nxt][0]=i;
    91         Max[i]=f[i];
    92         Splay(i,0);
    93     }
    94 }
  • 相关阅读:
    linux设备和驱动加载的先后顺序
    CCT之CAMERA TUNNING调试学习总结
    MTK Android software Tools工具的说明
    Android开发概要记录
    报表软件公司高价悬赏BUG,100块1个我真是醉了
    OV5640全景模式预览倒180度,拍照正常的问题
    一起学Python:TCP简介
    udp绑定信息
    应用:udp聊天器
    socket简介
  • 原文地址:https://www.cnblogs.com/refun/p/10362312.html
Copyright © 2020-2023  润新知