zoukankan      html  css  js  c++  java
  • 2019HDU多校第六场1009 Three Investigators——杨表

    题意

    给定一个 n 个元素的数列,从前 k 个元素中取5次不下降子序列,求取得的和的最大值(k从1至n)

    分析

           考虑将数字 a[i] 拆成 a[i] 个 a[i],比如 “4,1,2”→“4,4,4,4,1,2,2”,则问题转化为:找到最多 5 个不共享元素的不下降子序列,使得这些子序列包含的元素总量最多。可以证明,这等于杨氏图表前 5 层的长度之和。(手动模拟一下就能发现)

    考虑杨氏图表求解答案的过程:

    • 从 1 到 n 依次考虑序列中的每个数,将其插入杨氏图表的第一层中。
    • 插入 x 时,如果 x 不小于这一层的最大的数,则将 x 放在这一层的末尾;否则找到大于 x 的最小的数 y,将 y 替换为 x,并将 y 插入下一层。

            因为每一层的元素都有序,所以可以用数组维护,寻找 y 的过程可以用二分查找加速。

            但是对于本题来说,我们不能暴力地插入 a[i] 个 a[i]。考虑将杨表每一层中相同的元素合 并,用 std::map 记录每个元素的个数,那么当我们一次性插入 x 个 x 时,只需要将其插入 std::map 中,然后不断消费后继,将后继的元素个数减少即可,在减少的时候要将其作为 “p 个 q” 插入下一层中。 每一类数字被消费完毕后需要及时从 std::map 中删除,而每次插入会导致最多一种其它 数字被拆分,所以每层的插入次数至多为上一层的两倍。

           假设要求不超过 k 个子序列的答案,本题中 k = 5,则时间复杂度为 $O(2^kn log n)$。

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int K=5;
    map<int, ll>T[K];
    ll ans;
    int n;
    
    //在第o行插入p个x
    void insert(int o,int x,ll p){
      if(o>=K)return;
      T[o][x]+=p;
      ans+=p;
      while(p){
        map<int,ll>::iterator it=T[o].lower_bound(x+1);
        if(it==T[o].end())return;
        ll t=min(p,it->second);
        ans-=t;
        p-=t;
        insert(o+1,it->first,t);
        if(t==it->second)T[o].erase(it);else it->second-=t;
      }
    }
    
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d", &n);
            ans = 0;
            for(int i=0;i<K;i++) T[i].clear();
            for(int i = 1;i <= n;i++)
            {
                int tmp;
                scanf("%d", &tmp);
                insert(0, tmp, tmp);
                printf("%lld%c", ans, i == n ? '
    ' : ' ');
            }
        }
        return 0;
    }
  • 相关阅读:
    CentOS中rpm和yum到底有什么区别?
    Anaconda是个什么东东?
    Hadoop入门学习整理(三)
    Hadoop入门学习整理(二)
    CentOS6.10下安装MongoDB和Redis
    Linux 系统中环境变量/etc/profile、/etc/bashrc、~/.bashrc的区别
    一些想法
    时间
    周末
    条件
  • 原文地址:https://www.cnblogs.com/lfri/p/11326312.html
Copyright © 2011-2022 走看看