bzoj 3173 [Tjoi2013]最长上升子序列 (treap模拟+lis)

 [Tjoi2013]最长上升子序列

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2213  Solved: 1119
[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

 

Source

 

题解

    这道题目因为是顺序插入,求的是最长上升子序列,所以不改变当前位置的

    最长上升序列长度。

    放一个大的数在前面不影响,在中间,不影响,在后面,当当前位置为止的话也还是不影响的。

    所以只需要模拟出最后序列即可,怎么模拟,是关键。

    我是用平衡树维护的。

    点的编号即为当前插入点。

    最后求一次LIS即可。

  1 #include<cstring>
  2 #include<cmath>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cstdio>
  6 
  7 #define ls tr[p].l
  8 #define rs tr[p].r
  9 #define N 100007
 10 #define inf 1000000007
 11 using namespace std;
 12 inline int read()
 13 {
 14     int x=0,f=1;char ch=getchar();
 15     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
 16     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 17     return x*f;
 18 }
 19 
 20 int n,m,sz,rt,bh,top,now;
 21 char flag[3];
 22 int f[N],v[N],ans[N];
 23 struct Node
 24 {
 25     int l,r,val,siz,rnd;
 26 }tr[N];
 27 
 28 inline int rand()
 29 {
 30     static int seed=2333;
 31     return seed=(int)((((seed^998244353)+19260817ll)*19890604ll)%1000000007);
 32 }
 33 
 34 inline void update(int p)
 35 {
 36     tr[p].siz=tr[ls].siz+tr[rs].siz+1;
 37 }
 38 void lturn(int &p)
 39 {
 40     int t=tr[p].r;tr[p].r=tr[t].l;tr[t].l=p;
 41     tr[t].siz=tr[p].siz;update(p);p=t;
 42 }
 43 void rturn(int &p)
 44 {
 45     int t=tr[p].l;tr[p].l=tr[t].r;tr[t].r=p;
 46     tr[t].siz=tr[p].siz;update(p);p=t;
 47 }
 48 void ins(int &p,int x)
 49 {
 50     if (p==0)
 51     {
 52         p=++sz;
 53         tr[p].siz=1,tr[p].rnd=rand();
 54         return;
 55     }
 56     tr[p].siz++;
 57     if (tr[ls].siz<x)
 58     {
 59         ins(rs,x-tr[ls].siz-1);
 60         if (tr[rs].rnd<tr[p].rnd) lturn(p);
 61     }
 62     else
 63     {
 64         ins(ls,x);
 65         if (tr[ls].rnd<tr[p].rnd) rturn(p);
 66     }
 67 }
 68 void dfs(int p)
 69 {
 70     if (!p) return;
 71     dfs(ls);
 72     v[++now]=p;
 73     dfs(rs);
 74 }
 75 void solve()
 76 {
 77     memset(f,127,sizeof(f)),f[0]=-inf;
 78     for (int i=1;i<=n;i++)
 79     {
 80         int t=upper_bound(f,f+top+1,v[i])-f;
 81         if (f[t-1]<=v[i])
 82         {
 83             f[t]=min(f[t],v[i]);
 84             ans[v[i]]=t;
 85             top=max(t,top);
 86         }
 87     }
 88 }
 89 int main()
 90 {
 91     n=read();
 92     for (int i=1;i<=n;i++)
 93     {
 94         int x=read();now=i;
 95         ins(rt,x);
 96     }
 97     now=0,dfs(rt);
 98     solve();
 99     for (int i=1;i<=n;i++)
100     {
101         ans[i]=max(ans[i-1],ans[i]);
102         printf("%d\n",ans[i]);
103     }
104 }

 

posted @ 2017-12-08 13:57  Kaiser-  阅读(187)  评论(0编辑  收藏  举报