1 条题解
-
0
自动搬运
来自洛谷,原作者为

huangboming
哈哈中二与正义的伙伴吗?搬运于
2025-08-24 22:30:59,当前版本为作者最后更新于2024-08-02 20:11:45,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
前言
我有一个不用二分,极其简单的方法。
题意
给一个序列 ,你可以操作 次,每次将至多 个数字 ,求最大的 指数, 指数为有至少 个 。如
1 1 2 2 3这里最大的 指数为 。因为有 个大于等于的数,分别为2 2 3,而且 ,所以成立。而 不行因为只有 个大于等于的数3,而且 ,所以 为 不行。分析
首先,我们观察题意。
我们不难发现,题目想我们这么做:
- 当 的数的个数不 个时。
- 先算出在序列中小于 的同时最大的 个数( 为大于 的数的个数)。
- 将这 个数的数字大小加起来,叫做 。
- 算出 即所需大小的总和减 的值,叫做 。
- 最后比较 与 , 大小关系,看一下操作数量够不够。
那么如何用最短的时间求最大的 呢?
- 我们可以先
sort排序数列保证有单调性。(从小到大) - 后算出前缀和。
- 从小到大枚举 指数,当 时代表这个大小的 合法,相反则代表需要进行操作使这 个数加上 。 在第一次 时使其等于 。而后每次向前遍历 直到 。注意这里的 无需更改,因为
sort后的数列有单调性。 - 最后判断,当 要大于等于 中的最小值,且 。如果成立更新 即 指数。最最后输出 即可。
于是,我们不难调出如下代码。但是,需要注意的是!要特判 不为 即当我们查找大于当前的 的数字的个数(向前遍历),且要写当 指数不变的情况。一般就是 或是 即 乘上 太小了的情况,所以要每次记录更新 即最大的 指数。
时间复杂度及其证明
时间复杂度:
证明:用到了
sort所以极限情况是 ,遍历 h 和前缀和只用 ,求 时每次循环 的大小是不定义循环初始值的,一直遍历下去,所以只用 。本人代码:
#include<bits/stdc++.h> #define ll long long using namespace std; ll n,a[2000005],x,ans,k,l,qzh[200005],m,o; bool cmp(ll ai,ll bi){ return ai>bi; } int main(){ cin>>n>>k>>l; if(l>n)l=n;//特判l大于n时则多余的为无意义要舍去 m=k*l; for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } sort(a+1,a+1+n,cmp);//排序数列保证其有单调性(从小到大) for(int i=1;i<=n;i++){ qzh[i]=qzh[i-1]+a[i]; }//求前缀和 for(int i=1;i<=n;i++){//从小到大枚举h if(a[i]<i){ for(;a[o]<i&&o;o--){} //求大于h的数有哪些 if(i*(i-o)-qzh[i]+qzh[o]<=m&&i-a[i]<=k){//判断操作是否够 ans=i;//更新ans即最大的h指数。 } } else { ans=i;//更新ans在无需操作时最大的h指数。 o=i;//记录>h的个数 } } cout<<ans; return 0; }
- 1
信息
- ID
- 6674
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者