首页 > 代码库 > BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]

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]