做题记录 - CF1175D Array Splitting

洛谷题面

题面

n 个正整数不调整顺序分成 k 段,编号1k ,使得i=1naif(i)最大。
我们规定 f(i) 表示第 i 个数属于的段编号。

心路历程

Round 1

i=1naif(i)a1+a2f(2)+a3f(3)++anf(n)

由于相同的段中元素的 f() 相同,提取公因数,得:

a1+a2++ai+(ai+1+ai+2++aj)×2++(ak+ak+1++an)×k

拆括号,得:

a1+a2++ai+2ai+1+2ai+2++2aj++kak+kak+1++kan

思路中断。

Round 2

考虑分段求和,sumi 为第 i 段的和(考虑前缀和,后文 si 即前缀和数组),即:

ans=i=1ki×sumi

展开,得:

ans=s1+2(s2s1)++(k1)(sk1sk2)+k(sksk1)

继续化简,得:

ans=s12s1+2s23s2++(k1)sk1ksk1+ksk=(s1+s2++sk1)+ksk=kski=1k1si

时间复杂度 O(2n)
空间复杂度 O(2n)

跑样例后发现WA了

核心代码:

    read(n, k);
    for(int i = 1; i <= n; ++i) {
        read(a[i]);
        s[i] = s[i - 1] + a[i];
    }
    for(int i = 1; i < k; ++i) tot += s[i];
    cout << k * s[k] - tot;

Round DEBUG

检查推导,发现推导的第二步不合理。

Round 3

再推导一遍。

i=1naif(i)                                                                                                             =a1++ax1+2(ax1+ax1+1++ax2)2++(axk1++an)k=sx1+2(sx2sx1)++(k1)(sxk1sxk2)+k(snsxk1)                   =sx1+2sx22sx1++(k1)sx3(k1)sxk2+ksnksxk1                 =ksnsx1sx2sxk1                                                                                

想要让这个式子最大,只需要让sx1+sx2++sxk1 最小即可所以对前缀和数组排序,取第1k1 个即可。注意排序后不影响题面所说

不能动原始序列的顺序

ksn+i=1k1si

核心代码:

	read(n, k);
    for(int i = 1; i <= n; ++i) read(a[i]);
    for(int i = 1; i <= n; ++i) s[i] = s[i - 1] + a[i];
    sort(s + 1, s + n);
    for(int i = 1; i < k; ++i) tot += s[i];
    write(k * s[n] - tot);

WA

Round DEBUG

算了一下数据范围,会爆int

十年OI一场空,不开long long见祖宗

AC Code

#pragma region
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
#include <type_traits>

using namespace std;
using ll = long long;
using LL = ll;
const int INF = 0x7fffffff;
inline void IOS() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
}

template <typename T>
void read(T &x) {
	x = 0; char c = getchar(); int f = 0;
	for (; !isdigit(c); c = getchar())
		f |= c == '-';
	for (; isdigit(c); c = getchar())
		x = x * 10 + (c ^ '0');
	if (f) x = -x;
}
template <typename T, typename ... Args>
void read(T& a, Args&... args) {
    read(a), read(args...);
}

template <typename T>
void write(T x, char ed = '\n') {
    if(std::is_same<typename std::decay<T>, char>::value) {
        putchar(x); return ;
    }
	if (x < 0) putchar('-'), x = -x;
	static short st[30], tp;
	do st[++tp] = x % 10, x /= 10; while (x);
	while (tp) putchar(st[tp--] | '0');
	putchar(ed);
}

template <typename T, typename ... Args>
void write(T& a, Args&... args) {
    write(a), write(args...);
}

#pragma endregion

const int N = 5e5 + 10;

void Solve();

ll n, k;
vector<ll> a(N);
ll s[N];
ll tot = 0;

signed main() {
    IOS();
    Solve();
    return 0;
}

void Solve_throw() {
    read(n, k);
    for(ll i = 1; i <= n; ++i) {
        read(a[i]);
        s[i] = s[i - 1] + a[i];
    }
    sort(s + 1, s + n);
    for(ll i = 1; i < k; ++i) tot += s[i];
    cout << k * s[n] - tot;
}

void Solve() {
    read(n, k);
    for(int i = 1; i <= n; ++i) read(a[i]);
    for(int i = 1; i <= n; ++i) s[i] = s[i - 1] + a[i];
    sort(s + 1, s + n);
    for(int i = 1; i < k; ++i) tot += s[i];
    write(k * s[n] - tot);
}

---The End---

posted @   lyfandlzf  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示