BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]

Posted Candy?

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]相关的知识,希望对你有一定的参考价值。

3173: [Tjoi2013]最长上升子序列

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1613  Solved: 839
[Submit][Status][Discuss]

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


 

有一个离线做法:用treap动态把序列弄出来然后求lis

http://hzwer.com/6254.html

 

在线用splay

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#define N 100003  
using namespace std;  
int n,root;  
int key[N],size[N],ch[N][3],fa[N],sz,maxn[N],g[N];  
int get(int x)  
{  
    return ch[fa[x]][1]==x;  
}  
void update(int x)  
{  
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;  
    maxn[x]=g[x];  
    maxn[x]=max(maxn[x],maxn[ch[x][0]]);  
    maxn[x]=max(maxn[x],maxn[ch[x][1]]);  
    if (key[x]==1000000000||key[x]==0)  maxn[x]=0,g[x]=0;  
}  
void rotate(int x)  
{  
    int y=fa[x]; int z=fa[y]; int which=get(x);  
    if (z)  ch[z][ch[z][1]==y]=x;  
    fa[x]=z; ch[y][which]=ch[x][which^1]; fa[ch[y][which]]=y;  
    ch[x][which^1]=y; fa[y]=x;   
    update(y); update(x);  
}  
void splay(int x,int tar)  
{  
    for (int f;(f=fa[x])!=tar;rotate(x))    
     if (fa[f]!=tar)    
      rotate(get(x)==get(f)?f:x);    
    if (!tar)    
     root=x;    
}  
int find(int x)  
{  
    int now=root;   
    while (true)  
    {  
        if (x<=size[ch[now][0]])  
         now=ch[now][0];  
        else  
         {  
            int tmp=size[ch[now][0]]+1;  
            if (tmp==x) return now;  
            x-=tmp;  
            now=ch[now][1];  
         }  
    }  
}  
int main()  
{
    scanf("%d",&n);  
    root=++sz; key[sz]=1000000000; size[root]=2; fa[root]=0; ch[root][1]=++sz;  
    key[sz]=0; size[sz]=1; ch[sz][1]=ch[sz][0]=0; fa[sz]=root;  
    for (int i=1;i<=n;i++)  
     {  
        int x; scanf("%d",&x);  
        x++;  
        int aa=find(x);  
        int bb=find(x+1);   
        splay(aa,0); splay(bb,aa);  
        int t=ch[root][1];   
        ch[t][0]=++sz; fa[sz]=t; key[sz]=i; ch[sz][1]=ch[sz][0]=0;  
        size[sz]=1;  splay(t,0);   
        splay(sz,0);   
        g[sz]=maxn[ch[root][0]]+1;  update(sz);  
        printf("%d\n",maxn[sz]);  
     }  
}  

 

 

 

以上是关于BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]

bzoj3173 [Tjoi2013]最长上升子序列

BZOJ3173: [Tjoi2013]最长上升子序列

BZOJ3173: [Tjoi2013]最长上升子序列(树状数组)

bzoj3173 最长上升子序列 树状数组

bzoj3173最长上升子序列