P10139 [USACO24JAN] Nap Sort G

题目描述

Bessie 正在尝试使用她自己的排序算法对一个整数数组进行排序。她有一堆共 NNN1≤N≤2⋅1051\le N\le 2\cdot 10^51N2105)个整数 a1,a2,…,aNa_1,a_2,\ldots,a_Na1,a2,,aN1≤ai≤10111\le a_i\le 10^{11}1ai1011),她将会按排序顺序将这些数放入一个单独的数组中。她反复查找这堆数中的最小数,将其删除,同时将其添加到数组的末尾。Bessie 在 ppp 个数的堆中找到最小数需要花费 ppp 秒。

Farmer John 命令了农场中其他一些奶牛帮助 Bessie 完成任务,她们很懒,然而 Bessie 利用了这一点。她将整数分成两堆:Bessie 堆和助手堆。对于 Bessie 堆中的每个整数,她会正常执行她的算法。对于助手堆中的每个整数,她将其分配给不同的助手奶牛。Farmer John 有一个很大的农场,所以 Bessie 可以找来任意多的助手奶牛。如果助手收到整数 aia_iai,Bessie 会指示该牛小睡 aia_iai 秒,并在她们醒来时立即将该整数添加到数组末尾。如果 Bessie 和一个助手同时向数组添加整数,Bessie 的整数将优先被添加,因为她是领导者。如果多个助手被分配了相同的整数,她们会同时将多个该整数添加到数组中。

请帮助 Bessie 划分她的数,使得最终得到的数组是排序的,并使得排序该数组所需的时间最少。

输入格式

输入的第一行包含 TTT,为独立的测试用例的数量(1≤T≤101\le T\le 101T10)。

每个测试用例的格式如下:

每个测试用例的第一行包含 Bessie 的数组中的数的数量 NNN

下一行包含 a1,a2,…,aNa_1,a_2,\ldots,a_Na1,a2,,aN,为 Bessie 将要排序的整数。相同的数值可能会多次出现。

输入保证所有测试用例的 NNN 之和不超过 2⋅1052\cdot 10^52105

输出格式

对于每个测试用例输出一行,包含当 Bessie 以最优方案划分她的数时,排序该数组所需要的最小时间。

输入输出样例 #1

输入 #1

4
5
1 2 4 5 100000000000
5
17 53 4 33 44
4
3 5 5 5
6
2 5 100 1 4 5

输出 #1

6
15
5
6

说明/提示

样例解释 1

在第一个测试用例中,Bessie 可以将 1,21,21,2 分配给助手,将 4,5,10114,5,10^{11}4,5,1011 留给自己。

时间 事件
111 助手添加了 111
222 助手添加了 222
333 Bessie 添加了 444
555 Bessie 添加了 555
666 Bessie 添加了 101110^{11}1011

在第二个测试用例中,Bessie 的最优方案是自己对所有数进行排序。一个不正确的划分是 Bessie 将 444 分配给助手,其余的分配给她自己,因为助手将 444 添加到数组之前 Bessie 就会将 171717 添加到数组中。

在第三个测试用例中,Bessie 可以将所有数都分配给助手。

在第四个测试用例中,Bessie 可以将 1,4,51,4,51,4,5 分配给助手,将 2,5,1002,5,1002,5,100 留给自己。

时间 事件
111 助手添加了 111
333 Bessie 添加了 222
444 助手添加了 444
555 Bessie 添加了 555
555 助手添加了 555
666 Bessie 添加了 100100100

测试点性质

  • 测试点 222N≤16N\le 16N16
  • 测试点 3−53-535N≤150N\le 150N150
  • 测试点 6−86-868∑N≤5000\sum N\le 5000N5000
  • 测试点 9−119-11911:没有额外限制。
  • `在这里插入代码片
  • `#include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N=2e5+5;
    typedef long long ll;
    int t,n,c;
    ll a[N],m,p;
    int main() {
    int i,j;
    scanf(“%d”,&t);
    while(t) {
    –t;
    scanf(“%d”,&n);
    for(i=1; i<=n; ++i)
    scanf(“%lld”,a+i);
    sort(a+1,a+n+1);
    m=a[n];
    for(j=1; 1ll*(j+1)j/2<=a[n]; ++j) {//枚举集合大小p
    c=j;
    p=0;
    for(i=1; i<=n; ++i) {
    if(!c)
    break;
    if(a[i]>=p+c) {//依次往集合里面塞数
    p=p+c;//记录当前Bessie加数的时间
    –c;
    }
    if(i==n)
    m=min(m,1ll
    j*(j+1)/2);//找答案
    }
    if(m<a[n])
    break;
    }
    printf(“%lld\n”,m);
    }
    return 0;
    }
    在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

更多推荐