CF1175D Array Splitting
程序员文章站
2022-04-09 11:22:15
题目链接 题意 给出一个长度为$n$的序列$a$,要求分为恰好$K$段。第$i$个点的贡献是$a_i \times f(i)$,$f(x)$表示x所属的是第几段。 思路 非常巧妙的一个思路。 先让每个元素都选K遍。然后不断的删除。 具体做法就是,先求一遍前缀和。然后找出前缀和最小的$K 1$个前缀, ......
题意
给出一个长度为\(n\)的序列\(a\),要求分为恰好\(k\)段。第\(i\)个点的贡献是\(a_i \times f(i)\),\(f(x)\)表示x所属的是第几段。
思路
非常巧妙的一个思路。
先让每个元素都选k遍。然后不断的删除。
具体做法就是,先求一遍前缀和。然后找出前缀和最小的\(k-1\)个前缀,将其从答案中减去。初始答案为所有元素和\(\times k\)
这样被减j遍的元素就位于第\(k-j\)段中。因为是前缀和。所以前边点被减的次数一定大于等于后边。然后就符合题意了。
代码
/* * @author: wxyww * @date: 2019-06-06 07:50:48 * @last modified time: 2019-06-06 07:56:06 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; const int n = 300000 + 100; ll read() { ll x=0,f=1;char c=getchar(); while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } ll a[n]; int main() { int n = read(),k = read(); for(int i = 1;i <= n;++i) a[i] = read() + a[i - 1]; ll ans = a[n] * k; sort(a + 1,a + n); for(int i = 1;i <= k - 1;++i) ans -= a[i]; cout<<ans; return 0; }
推荐阅读
-
PHP错误Cannot use object of type stdClass as array in错误的解决办法
-
js中Array对象的常用遍历方法详解
-
2个自定义的PHP in_array 函数,解决大量数据判断in_array的效率问题
-
深入array multisort排序原理的详解
-
php利用array_search与array_column实现二维数组查找
-
JavaScript中循环遍历Array与Map的方法小结
-
Javascript数组Array基础介绍
-
Javascript数组Array方法解读
-
Python当中的array数组对象实例详解
-
Python列表list数组array用法实例解析