zoukankan      html  css  js  c++  java
  • 【bzoj 3173】[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

    易得,令f[i]表示以数字i结尾的最长上升子序列长度,则新加入一个数时不会影响到其他的f[i]。

    在线写法:用平衡树直接模拟,每一次用位置的前缀f[i]的最大值+1来作为当前的新加入的数的f[i],然后将其插入到指定位置。输出答案时直接查找当前所有f[i]的最大值。

    离线写法:求出最终序列然后nlogn求一次LIS即可,可以用树状数组或平衡树实现。

    【fhq-treap 在线】

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdlib>
     5 using namespace std;
     6 const int N=1e5+5;
     7 int n,root,cnt,rt1,rt2,pos,ch[N][6];
     8 #define lc ch][0
     9 #define rc ch][1
    10 #define rnd ch][2
    11 #define sz ch][3
    12 #define v ch][4
    13 #define mx ch][5
    14 int read()
    15 {
    16     int x=0,f=1;char c=getchar();
    17     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    18     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    19     return x*f;
    20 }
    21 void up(int w)
    22 {
    23     w[sz]=w[lc][sz]+w[rc][sz]+1;
    24     w[mx]=max(w[lc][mx],w[rc][mx]);
    25     w[mx]=max(w[mx],w[v]);
    26 }
    27 void split(int w,int& l,int& r,int k)
    28 {
    29     if(!w){l=r=0;return;}
    30     int lson=w[lc][sz];
    31     if(k<=lson){r=w;split(w[lc],l,w[lc],k);}
    32     else {l=w;split(w[rc],w[rc],r,k-lson-1);}
    33     up(w);
    34 }
    35 int merge(int a,int b)
    36 {
    37     if(!a||!b)return a+b;
    38     if(a[rnd]<b[rnd]){a[rc]=merge(a[rc],b);up(a);return a;}
    39     else {b[lc]=merge(a,b[lc]);up(b);return b;}
    40 }
    41 void ins(int& w,int x,int k)
    42 {
    43     if(x[rnd]<w[rnd]||!w){split(w,x[lc],x[rc],k);w=x;up(w);return;}
    44     int lson=w[lc][sz];
    45     if(k<=lson)ins(w[lc],x,k);
    46     else ins(w[rc],x,k-lson-1);
    47     up(w);
    48 }
    49 int query(int pos)
    50 {
    51     rt1=rt2=0;split(root,rt1,rt2,pos);
    52     int ans=rt1[mx];root=merge(rt1,rt2);
    53     return ans;
    54 }
    55 int main()
    56 {
    57     n=read();
    58     for(int i=1;i<=n;i++)
    59     {
    60         pos=read();
    61         cnt++;cnt[v]=query(pos)+1;
    62         cnt[sz]=1;cnt[rnd]=rand();
    63         ins(root,cnt,pos);
    64         printf("%d
    ",root[mx]);
    65     }
    66     return 0;
    67 }
    View Code

    【树状数组 离线】

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=1e5+5;
     6 int n,id,cnt,f[N],ans[N],a[N],num[N],bit[N];
     7 int read()
     8 {
     9     int x=0,f=1;char c=getchar();
    10     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    11     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    12     return x*f;
    13 }
    14 int lowbit(int x){return x&(-x);}
    15 void ins(int x){while(x<=n)bit[x]--,x+=lowbit(x);}
    16 int pos(int x)
    17 {
    18     int now=0,ans=0;
    19     for(int i=17;i>=0;i--)
    20     {
    21         now+=(1<<i);
    22         if(now<n&&ans+bit[now]<x)ans+=bit[now];
    23         else now-=(1<<i);
    24     }
    25     return now+1;
    26 }
    27 int main()
    28 {
    29     n=read();
    30     for(int i=1;i<=n;i++)
    31     {
    32         a[i]=read();bit[i]++;
    33         if(i+lowbit(i)<=n)bit[i+lowbit(i)]+=bit[i];
    34     }
    35     for(int i=n;i>=1;i--)
    36         id=pos(a[i]+1),num[id]=i,ins(id);
    37     for(int i=1;i<=n;i++)
    38     {
    39         id=lower_bound(f+1,f+cnt+1,num[i])-f;
    40         if(id>cnt)f[++cnt]=num[i];
    41         else f[id]=num[i];
    42         ans[num[i]]=id;
    43     }
    44     for(int i=1;i<=n;i++)ans[i]=max(ans[i],ans[i-1]),printf("%d
    ",ans[i]);
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    dubbo源码阅读-服务订阅(八)之本地订阅(injvm)
    dubbo源码阅读-服务订阅(八)之主流程
    dubbo源码阅读-服务暴露(七)之远程暴露(dubbo)
    dubbo源码阅读-配置(二)之API配置
    dubbo源码阅读-容器启动(六)
    LIRe 源代码分析 6:检索(ImageSearcher)[以颜色布局为例]
    LIRe 源代码分析 5:提取特征向量[以颜色布局为例]
    LIRe 源代码分析 4:建立索引(DocumentBuilder)[以颜色布局为例]
    智能电视大战背后的秘密
    二线视频网站突围战
  • 原文地址:https://www.cnblogs.com/zsnuo/p/7918389.html
Copyright © 2011-2022 走看看