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 ? ‘\n‘ : ‘ ‘);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lfri/p/11326312.html

时间: 2024-07-31 03:04:29

2019HDU多校第六场1009 Three Investigators——杨表的相关文章

多校第六场 HDU 4927 JAVA大数类

题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 思路:这题实在是太晕了,比赛的时候搞了四个小时,从T到WA,唉--对算组合还是不太了解啊,现在对组合算比较什么了-- import java.io.*; import java.math.*; import java.util.*; public class Main { public static void main(String[] args) { Sca

HDU 4923 Room and Moor (多校第六场C题) 单调栈

Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B1, B2,... , BN} of the same length, which satisfies that: Input The inp

2014多校第六场 1005 || HDU 4925 Apple Tree

题目链接 题意 : 给你一块n×m的矩阵,每一个格子可以施肥或者是种苹果,种一颗苹果可以得到一个苹果,但是如果你在一个格子上施了肥,那么所有与该格子相邻(指上下左右)的有苹果树的地方最后得到的苹果是两倍,如果(i,j)有一颗苹果树,(i-1,j)与(i,j+1)施了肥,那么苹果应该是1的两倍2,2的两倍4,最后是4个苹果,问你怎么安排苹果和施肥的格子使最后得到的苹果最多. 思路 : 画了图就可以看出来,苹果和苹果,肥与肥之间不要相邻就好了,所有的苹果之间都有施肥,所有施肥的格子都被苹果隔开了才能

【HDU】4923 Room and Moor(2014多校第六场1003)

Room and Moor Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 263    Accepted Submission(s): 73 Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0

2014多校第六场 || HDU 4927 Series 1(杨辉三角组合数)

题目链接 题意 : n个数,每操作一次就变成n-1个数,最后变成一个数,输出这个数,操作是指后一个数减前一个数得到的数写下来. 思路 : 找出几个数,算得时候先不要算出来,用式子代替,例如: 1 2 3 4 5 6 (2-1) (3-2) (4-3) (5-4)(6-5) (3-2-2+1)(4-3-3+2)(5-4-4+3)(6-5-5+4) (4-3-3+2-3+2+2-1)(5-4-4+3-4+3+3-2)(6-5-5+4-5+4+4-3) (5-4-4+3-4+3+3-2-4+3+3-2

2014 HDU多校弟六场J题 【模拟斗地主】

这是一道5Y的题目 有坑的地方我已在代码中注释好了 QAQ Ps:模拟题还是练的太少了,速度不够快诶 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <climits> #include <cstring> #include <cmath> #inclu

2014多校第六场 1010 || HDU 4930 Fighting the Landlords (模拟)

题目链接 题意 : 玩斗地主,出一把,只要你这一把对方要不了或者你出这一把之后手里没牌了就算你赢. 思路 : 一开始看了第一段以为要出很多次,实际上只问了第一次你能不能赢或者能不能把牌出尽. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std ; 6 7 char str1[20],str2[20] ; 8 int hash1[20],hash2[2

2016多校第六场1001-1003(hdu5793&amp;hdu5794&amp;hdu5795)

这场就做出一道题,怎么会有窝这么辣鸡的人呢? 1001 很复杂的公式,打表找的规律,最后是m^0+m^1+...+m^n,题解直接是(m^(n+1)-1)/(m-1),长姿势,原来还能化简……做出来的题不写题解了. 1002 一个棋盘,走棋的姿势要满足(x1-x2)^2+(y1-y2)^2==5,也就是以“日”字走,且只能向右下走. 其中有一些障碍不能经过,注意障碍有可能在终点,求从(1,1)走到(n,m)的路径数. 容斥+组合数 这题的简单版CF559C(对啊,我做过这题,我还是没做出来,wa

HDU 5335 多校第4场 1009 Walk Out

Walk Out Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1794    Accepted Submission(s): 340 Problem Description In an n?m maze, the right-bottom corner is the exit (position (n,m) is the exit)