[CCPC 2024 Shandong I] 分割序列题解
题目描述
给定长度为 n 的整数序列 a1,a2,⋯,an,请将序列分成 k 段连续且非空的子数组,使得序列中的每个元素恰属于一个子数组。令 si 表示从左到右第 i 个子数组里的元素之和,对于每个 1≤k≤n,求下式的最大值。
i=1∑ki×si
更正式地,对于每个 1≤k≤n,令 r0=0 以及 rk=n,您需要找到 (k−1) 个整数 r1,r2,⋯,rk−1 满足 r0<r1<r2<⋯<rk−1<rk,并最大化下式的值。
i=1∑ki×(j=ri−1+1∑riaj)
输入格式
有多组测试数据。第一行输入一个整数 T 表示测试数据组数,对于每组测试数据:
第一行输入一个整数 n(1≤n≤5×105)表示序列的长度。
第二行输入 n 个整数 a1,a2,⋯,an(−106≤ai≤106)表示序列。
保证所有数据 n 之和不超过 5×105。
输出格式
每组数据输出一行 n 个由单个空格分隔的整数 v1,v2,⋯,vn,其中 vi 表示 k=i 时的答案。
输入输出样例
输入 #1复制
2 6 1 3 -4 5 -1 -2 1 100
输出 #1复制
2 4 5 3 1 -2 100
说明/提示
对于第一组样例数据,考虑 k=3,可以将序列分割为 {{1},{3,−4},{5,−1,−2}}。答案是 1×1+2×(3−4)+3×(5−1−2)=5。
思路
贪心,取最大即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long t,n,a[500005],b[500005],lk=0;
bool cmp(long long a1,long long b1){
return a1>b1;
}
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
b[n+1]=0;
for(int i=n;i>=1;i--){
b[i]=b[i+1]+a[i];
}
lk=b[1];
sort(b+2,b+n+1,cmp);
for(int i=1;i<=n;i++){
if(i!=1){
lk+=b[i];
}
cout<<lk<<" ";
}
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号