专栏文章

题解:P14562 宇宙

P14562题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@min1zimk
此快照首次捕获于
2025/12/01 19:15
3 个月前
此快照最后确认于
2025/12/01 19:15
3 个月前
查看原文

P14562 宇宙

思路

被 TLE 创死了。
uju_j 升序排序后,设前 mm 个元素满足 ujxu_j \le x,则求和式可表示为 mxj=1mujm\cdot x - \sum_{j=1}^m u_j。用前缀和算该值,用双指针找到每个 kk 对应的最优 mm
  1. vjv_j 转换为 uj=vj1u_j = v_j - 1,并对 uju_j 升序排序。
  2. 对于前缀和数组 SS,其中 S[m]=j=1mujS[m] = \sum_{j=1}^m u_j
  3. 对每个 kk,用双指针维护最优的 mm,使得 S[m]mk\frac{S[m]}{m-k} 最小(对应最大的 xx),最终 x=S[m]mkx = \lfloor \frac{S[m]}{m-k} \rfloor 即可。
时间复杂度为 O(nlogn)\mathcal{O}(n \log n)
CodeCPP
#include<bits/stdc++.h>
using namespace std;
#define int __int128
constexpr int N = 78787878;
int arr1[N], arr2[N], arr3[N], ans[N], n, m, sum = 2;
void write(int x){
    if(x == 0) return;
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x / 10) write(x / 10);
    putchar(x % 10 + '0');
}
int read(){
    int x = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x;
}
signed main(){
    n = read(), m = read();
    int nn = m, mm = n;
    for(int i = 0; i < nn; i++){
        int x;
        x = read();
        arr1[i] = x;
        arr2[i] = arr1[i] - 1;
    }
    sort(arr2, arr2 + nn);
    arr3[0] = 0;
    for(int i = 1; i <= nn; i++) arr3[i] = arr3[i - 1] + arr2[i - 1];
    for(int k = 1; k <= nn - 1; k++){
        sum = max(sum, (k + 1));
        while(sum < nn){
            int t1 = sum - k;
            int t2 = (sum + 1) - k;
            int a = arr3[sum] * t2;
            int b = arr3[sum + 1] * t1;
            if(a > b){
                sum++;
            }else{
                break;
            }
        }
        int t = sum - k;
        ans[k - 1] = arr3[sum] / t;
    }
    for(int i = 0; i < nn - 1; i++){
        if(ans[i] == 0) putchar('0');
        else write(ans[i]);
        if(i != nn - 2) putchar(' ');
        else putchar('\n');
    }
    return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...