[APIO2014]序列分割
来源:互联网 发布:达内java培训班有用吗 编辑:程序博客网 时间:2024/06/05 19:41
你正在玩一个关于长度为 nn 的非负整数序列的游戏。这个游戏中你需要把序列分成 k+1k+1 个非空的块。为了得到 k+1k+1 块,你需要重复下面的操作 kk 次:
选择一个有超过一个元素的块(初始时你只有一块,即整个序列)选择两个相邻元素把这个块从中间分开,得到两个非空的块。
每次操作后你将获得那两个新产生的块的元素和的乘积的分数。你想要最大化最后的总得分。
输入格式
第一行包含两个整数 nn 和 kk。保证 k+1≤nk+1≤n。
第二行包含 nn 个非负整数 a1,a2,…,ana1,a2,…,an (0≤ai≤104)(0≤ai≤104),表示前文所述的序列。
输出格式
第一行输出你能获得的最大总得分。
第二行输出 kk 个介于 11 到 n−1n−1 之间的整数,表示为了使得总得分最大,你每次操作中分开两个块的位置。第 ii 个整数 sisi 表示第 ii 次操作将在 sisi 和 si+1si+1 之间把块分开。
如果有多种方案使得总得分最大,输出任意一种方案即可。
样例一
input
7 3
4 1 3 4 0 2 3
output
108
1 3 5
explanation
你可以通过下面这些操作获得 108108 分:
初始时你有一块 (4,1,3,4,0,2,3)(4,1,3,4,0,2,3)。在第 11 个元素后面分开,获得 4×(1+3+4+0+2+3)=524×(1+3+4+0+2+3)=52 分。你现在有两块 (4),(1,3,4,0,2,3)(4),(1,3,4,0,2,3)。在第 33 个元素后面分开,获得 (1+3)×(4+0+2+3)=36(1+3)×(4+0+2+3)=36 分。你现在有三块 (4),(1,3),(4,0,2,3)(4),(1,3),(4,0,2,3)。在第 55 个元素后面分开,获得 (4+0)×(2+3)=20(4+0)×(2+3)=20 分。
所以,经过这些操作后你可以获得四块 (4),(1,3),(4,0),(2,3)(4),(1,3),(4,0),(2,3) 并获得 52+36+20=10852+36+20=108 分。
限制与约定
第一个子任务共 11 分,满足 1≤k
/*50分的暴力: 复杂度: O(kn^2)首先要发现一个性质: 只要选定了切的位置,不论什么顺序切,答案都是一样例如: 把序列切两次,每段的和分为 x1 x2 x3,先在1,2间切的得分: x1*(x2+x3)+x2*x3 = x1*x2+x1*x3+x2*x3先在1,3间切的得分: x3*(x1+x2)+x1*x2 = x1*x3+x1*x2+x1*x2所以就可以用dp(i,j) 表示前j个数切i次的总得分,sum是前缀和dp(i,j) = max(dp(i-1, k) + (sum(j)-sum(k))*sum(k));k是枚举<j的区间里的一个切点*/#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>using namespace std;const int maxx=1e5+5;#define For(i,a,b) for(register int i=(a);i<=(b);++i)#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)#define LL long longint read(){ char x=getchar(); int u=0; while(!isdigit(x)) x=getchar(); while(isdigit(x)) u=(u<<3)+(u<<1)+(x^48), x=getchar(); return u;}LL sum[maxx],dp[201][maxx],to[201][maxx],n,k;int main(){#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout);#endif n=read(); k=read(); For(i,1,n) sum[i]=sum[i-1]+read(); For(i,1,n) For(j,1,i-1) For(p,1,k) if(dp[p][i]<=dp[p-1][j]+sum[j]*(sum[i]-sum[j])){ dp[p][i]=dp[p-1][j]+sum[j]*(sum[i]-sum[j]); to[p][i]=j; } printf("%lld\n",dp[k][n]); int i=n; Rep(j,k,1){ i=to[j][i]; printf("%d ",i); } return 0;}/*在50分的暴力基础上,因为原式大概为 dp(i)=max(dp(k) + sum(i) * sum(k) - sum(k)^2);可以斜率优化 假设 j<k 即可以从k转移 sum(i) > [ sum(j)^2-sum(k)^2 + dp(k) - dp(j) ] / (sum(j) -sum(k);输出方案时,只需要记录每次由谁转移洛谷上只开了128M,uoj上开了256M,所以洛谷上会MLE幸好dp(i,j) =max(dp(i-1, k) +sum(...))每次只由上一层转移过来,所以可以开滚动数组*/#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>using namespace std;const int maxx=1e5+1;#define For(i,a,b) for(register int i=(a);i<=(b);++i)#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)#define LL long long#define sqr(x) ((x)*(x))int read(){ char x=getchar(); int u=0; while(!isdigit(x)) x=getchar(); while(isdigit(x)) u=(u<<3)+(u<<1)+(x^48), x=getchar(); return u;}LL sum[maxx],dp[2][maxx],n,k,p;int to[201][maxx];int q[maxx],l,r;bool type=0;double slope(int x,int y){ // 斜率 if(sum[x]==sum[y]) return -1e18; return (double)(sqr(sum[x]) - sqr(sum[y])-dp[type^1][x] + dp[type^1][y]) / (double) (sum[x]-sum[y]);}int main(){#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout);#endif n=read(); k=read(); For(i,1,n) sum[i]=sum[i-1]+read(); for(p=1; p<=k; ++p){ l=r=0; type^=1; For(i,1,n){ while(l<r && slope(q[l],q[l+1]) <= sum[i]) ++l; dp[type][i]=dp[type^1][q[l]]+sum[q[l]]*(sum[i]-sum[q[l]]); to[p][i]=q[l]; while(l<r && slope(q[r-1],q[r]) >= slope(q[r],i)) --r; q[++r]=i; } } printf("%lld\n",dp[type][n]); int i=n; Rep(j,k,1){ i=to[j][i]; printf("%d ",i); } return 0;}
阅读全文
1 0
- APIO2014序列分割bzoj3675
- bzoj3675: [Apio2014]序列分割
- [BZOJ3675][Apio2014]序列分割
- [BZOJ3675] [Apio2014]序列分割
- bzoj3675【APIO2014】序列分割
- 【APIO2014】序列分割
- 【APIO2014】序列分割(sequence)
- 3675: [Apio2014]序列分割
- BZOJ3675 Apio2014 序列分割
- bzoj3675[Apio2014] 序列分割
- bzoj3675: [Apio2014]序列分割
- bzoj3675: [Apio2014]序列分割
- 3675: [Apio2014]序列分割
- BZOJ3675: [Apio2014]序列分割
- BZOJ3675: [Apio2014]序列分割
- [APIO2014]序列分割
- bzoj3675 [Apio2014]序列分割
- bzoj3675 [Apio2014]序列分割
- 设计模式——抽象工厂模式
- 寻址方式
- 通过js优化web性能
- 混合背包
- JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解
- [APIO2014]序列分割
- 阿里巴巴Java开发手册一周年最终版
- 破解CentOS7 口令的两种方法
- Linux操作系统命令学习第五天
- 机器学习与人类比较
- 线程插入
- EffectiveJava
- [模板] exgcd模板解不定方程
- Mac串口助手源代码详解(下)