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


    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3173

    题意:向序列中动态插入$1~n$排列元素,求出插入每个元素后最长上升子序列长度。

    如Claris所言,面对这种数据结构,必有高论。如果只想着数据结构,我们可以通过平衡树动态维护序列,同时使用树状数组计算最长上升子序列。

    但是我们不是猩猩不是数据结构狂人,我们毕竟还是要本着能不上树就不上树能少用数据结构就少用的原则来设计算法的。

    重新考虑这个题目。本题没有要求强制在线,于是我们把整个操作倒过来看,于是问题就变成了不停地删去序列中某个元素后求出当前最长上升子序列长度。

    然后,不要忘了一个重要条件:这个东西是从小到大插入的。

    从小到大插入,意味着插入一个数之后最长上升子序列发生变化的唯一可能就是以这个数结尾。

    那么我们就维护一下删掉每个数之前以这个数结尾的最长上升子序列就好了,最后输出答案时,将这个与前一个比较,短就直接将当前这个数赋值成为上一个。

    说得简单……但是这道题真的是一个树状数组综合运用……具体看代码吧……

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 int lowbit(int x)
     7 {
     8     return x&(-x);
     9 }
    10 const int maxn=100005;
    11 int C[maxn],n;
    12 void Modify(int pos,int val)
    13 {
    14     for(;pos<=n;pos+=lowbit(pos))C[pos]+=val;
    15 }
    16 void Maximum(int pos,int val)
    17 {
    18     for(;pos<=n;pos+=lowbit(pos))C[pos]=max(C[pos],val);
    19 }
    20 int Query_kth(int k)
    21 {
    22     int cnt=0,ans=0;
    23     for(int i=17;~i;i--)
    24     {
    25         ans+=(1<<i);
    26         if(ans>=n||cnt+C[ans]>=k)ans-=(1<<i);
    27         else cnt+=C[ans];
    28     }
    29     return ans+1;
    30 }
    31 int Query_max(int pos)
    32 {
    33     int res=0;
    34     for(;pos;pos-=lowbit(pos))res=max(res,C[pos]);
    35     return res;
    36 }
    37 int a[maxn],b[maxn],f[maxn];
    38 int haha()
    39 {
    40     scanf("%d",&n);
    41     for(int i=1;i<=n;i++)
    42     {
    43         scanf("%d",&a[i]);C[i]++;
    44         if((i+lowbit(i))<=n)C[i+lowbit(i)]+=C[i];
    45     }
    46     int tmp;
    47     for(int i=n;i;i--)b[tmp=Query_kth(a[i]+1)]=i,Modify(tmp,-1);
    48     memset(C,0,sizeof(C));
    49     for(int i=1;i<=n;i++)f[b[i]]=Query_max(b[i])+1,Maximum(b[i],f[b[i]]);
    50     for(int i=1;i<=n;i++)printf("%d
    ",f[i]<f[i-1]?(f[i]=f[i-1]):f[i]);
    51 }
    52 int sb=haha();
    53 int main(){;}
    bzoj3173
  • 相关阅读:
    asp.net mvc 学习
    ms sqlserver 清除数据库日志脚本
    DB、ETL、DW、OLAP、DM、BI关系结构图
    日期维度(周一为每周第一天)
    关于C#操作Excel,复制Sheet的记录
    ms sqlserver 登录失败 错误:4064
    通过sqlserver sa密码修改windows操作系统密码
    ssas 为绑定指定的大小太小,导致一个或多个列值被截断
    ExpandoObject的使用
    【慕课网实战】Spark Streaming实时流处理项目实战笔记三之铭文升级版
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7780435.html
Copyright © 2020-2023  润新知