zoukankan      html  css  js  c++  java
  • bzoj3173:[Tjoi2013]最长上升子序列

    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

    分析一下Treap的正确性:假设插入点p,再插入点q,由题意可知q>p,所以有两种情况,第一种,q插在p的前面,第二种,插在p的后面,由于插在p前面,q又大于p,所以q的存在不会影响p的LIS,如果插在p的后面,则Treap也会将其插在p的后面,所以同样不会影响结果,由此可知,可使用Treap来实现插入。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #define inf 1<<29
      5 #define maxn 100010
      6 int cnt,tcnt,ans[maxn],n,v[maxn],root;
      7 using namespace std;
      8 struct treap{
      9     int pri,lc,rc,siz;
     10 }a[maxn];
     11 void pushup(int o){a[o].siz=a[a[o].lc].siz+a[a[o].rc].siz+1;}
     12 void lturn(int &o)
     13 {
     14     int t=a[o].rc;
     15     a[o].rc=a[t].lc;
     16     a[t].lc=o;
     17     a[t].siz=a[o].siz;
     18     pushup(o);
     19     o=t;
     20     return ;
     21 }
     22 void rturn(int &o)
     23 {
     24     int t=a[o].lc;
     25     a[o].lc=a[t].rc;
     26     a[t].rc=o;
     27     a[t].siz=a[o].siz;
     28     pushup(o);
     29     o=t;
     30     return ;
     31 }
     32 void insert(int &o,int rank)
     33 {
     34     if(!o)
     35     {
     36         o=++cnt;
     37         a[o]=(treap){rand(),0,0,1};
     38         return ;
     39     }
     40     a[o].siz++;
     41     if(rank<=a[a[o].lc].siz)
     42     {
     43         insert(a[o].lc,rank);
     44         if(a[a[o].lc].pri>a[o].pri)rturn(o);
     45     }
     46     else 
     47     {
     48         insert(a[o].rc,rank-a[a[o].lc].siz-1);
     49         if(a[a[o].rc].pri>a[o].pri)lturn(o);
     50     }
     51     return ;
     52 }
     53 void dfs(int o)
     54 {
     55     if(!o)return ;
     56     dfs(a[o].lc);
     57     v[++tcnt]=o;
     58     dfs(a[o].rc);
     59     return ;
     60 }
     61 void solve()
     62 {
     63     int f[maxn],len=0;
     64     for(int i=1 ; i<=n ; ++i )
     65     {
     66         int l=1,r=len;
     67         if(v[i]>f[len])
     68         {
     69             f[++len]=v[i];
     70             ans[v[i]]=len;
     71             continue;
     72         }
     73         while(r>l)
     74         {
     75             int m=(r+l)>>1;
     76             if(v[i]>f[m])l=m+1;
     77             else r=m;
     78         }
     79         f[l]=v[i];
     80         ans[v[i]]=l;
     81     }
     82     return ;
     83 }
     84 int main()
     85 {
     86     scanf("%d",&n);
     87     srand(n);
     88     for(int i=1 ; i<=n ; ++i)
     89     {
     90         int b;
     91         scanf("%d",&b);
     92         insert(root,b);
     93     }
     94     dfs(root);
     95     solve();
     96     for(int i=1 ; i<=n ; ++i)
     97     {
     98         ans[i]=max(ans[i],ans[i-1]);
     99         printf("%d
    ",ans[i]);
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    大学阶段最后的交流
    JavaScript的一些基础性知识
    CSS的一些总结
    JavaWeb的一些理解
    Java Web之XML基础
    Java基础增强
    反射的理解
    Java网络编程
    Java 中剩下的流以及线程方面的知识
    Java中的流操作
  • 原文地址:https://www.cnblogs.com/fujudge/p/7550699.html
Copyright © 2011-2022 走看看