【BZOJ】3675: [Apio2014]序列分割
http://www.lydsy.com/JudgeOnline/problem.php?id=3675
题意:给一个n个数字的序列,每一次分割的贡献是$sum(left, mid)*sum(mid+1, right)$,其中$left$表示本序列的最左边,$right$同理,$mid$是分割的位置(即在$mid$和$mid+1$中分割)。每次分割序列会变成两半。问分割k次得到的最大贡献和。n<=100000, k<=200
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll s[N], d[2][N];
int n, K, q[N], fr, ta;
int main() {
scanf("%d%d", &n, &K);
for(int i=1; i<=n; ++i) scanf("%lld", &s[i]), s[i]+=s[i-1];
ll *now=d[0], *last=d[1];
for(int p=1; p<=K; ++p) {
fr=ta=0; q[ta++]=0;
for(int i=1; i<=n; ++i) {
while(fr!=ta-1 && last[q[fr]]-last[q[fr+1]]<=(s[q[fr]]-s[q[fr+1]])*(s[n]-s[i])) fr++;
int j=q[fr];
now[i]=last[j]+(s[i]-s[j])*(s[n]-s[i]);
while(fr!=ta-1 && (last[i]-last[q[ta-2]])*(s[q[ta-1]]-s[q[ta-2]])>=(last[q[ta-1]]-last[q[ta-2]])*(s[i]-s[q[ta-2]])) --ta;
q[ta++]=i;
}
swap(last, now);
}
ll ans=0;
for(int i=1; i<=n; ++i) ans=max(ans, last[i]);
printf("%lld\n", ans);
return 0;
}
听laekov说要分析一下特殊的性质,于是分析了一下。。可以发现,每一个块对答案的贡献是$sum(本块)*sum(剩下的元素)$,最后当然要除以2,因为重复算了两次。但是可以用乱搞一下。。。
考虑dp,设$d(i, j)$表示这个序列在$i$分割了$j$次得到的答案且第$j$次是在$i$分割的。
容易得到:
$d(i, j)=max(d(k, j-1)+sum(k+1, i)*sum(i+1, n))$
大概就是表示得到的块为$(k+1, i)$,然后由于前面算过了对这些值的乘积,所以不用再计算一次(否则答案要除以二= =),于是我们直接乘一下后面的和即可。。
然后另$s(n)=\sum_{i=1}^{n} a[i]$,则
$d(i, j)=max(d(k, j-1)+(s(i)-s(k))*(s(n)-s(i)))$
然后搞搞斜率优化即可= =
(好久没写了然后发现自己维护上凸壳时整个人sb了。。。。队尾居然不是维护凸壳然后交了4发wa居然没发现。。
【BZOJ】3675: [Apio2014]序列分割的更多相关文章
- 【斜率DP】BZOJ 3675:[Apio2014]序列分割
3675: [Apio2014]序列分割 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1066 Solved: 427[Submit][Statu ...
- BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )
WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...
- bzoj 3675 [Apio2014]序列分割(斜率DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3675 [题意] 将n个数的序列分割k次,每次的利益为分割后两部分数值和的积,求最大利益 ...
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
题目链接 BZOJ 3675 首先最后的答案和分割的顺序是无关的, 那么就可以考虑DP了. 设$f[i][j]$为做了$i$次分割,考虑前$j$个数之后的最优答案. 那么$f[i][j] = max( ...
- 动态规划(斜率优化):BZOJ 3675 [Apio2014]序列分割
Description 小H最近迷上了一个分割序列的游戏.在这个游戏里,小H需要将一个长度为N的非负整数序列分割成k+l个非空的子序列.为了得到k+l个子序列, 小H将重复进行七次以下的步骤: 1.小 ...
- bzoj 3675: [Apio2014]序列分割
Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
洛谷传送门 题目大意:让你把序列切割k次,每次切割你能获得 这一整块两侧数字和的乘积 的分数,求最大的分数并输出切割方案 神题= = 搞了半天也没有想到切割顺序竟然和答案无关...我太弱了 证明很简单 ...
- bzoj 3675: [Apio2014]序列分割【斜率优化dp】
首先看这个得分方式,容易发现就相当于分k段,每段的值和两两乘起来. 这样就很容易列出dp方程:设f[i][j]为到j分成分成i段,转移是 \[ f[i][j]=max { f[k][j]+s[k]*( ...
- BZOJ 3675: [Apio2014]序列分割 动态规划 + 斜率优化 + 卡精度
Code: #include<bits/stdc++.h> #define N 100006 #define M 205 #define ll long long #define setI ...
- 3675: [Apio2014]序列分割
Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...
随机推荐
- hdu 1556:Color the ball(线段树,区间更新,经典题)
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 取得表中数据的insert语句
Build Insert Statements for the Existing Data in Tables 下面这个脚本实现了取得一个非空表中的所有insert语句 This script bui ...
- html5 方框内的小球
html5 方框内的小球 版本一 <!DOCTYPE html> <html> <head lang="en"> <meta charse ...
- C#DataGridView合计处理
网上查了一些关于合计的代码 ,但发现大都都不尽人意,就自己再根据资料改了一下. #region 合计 //调用方法示例 //HeJi heji = null; //heji = new HeJi(la ...
- [SQL]查询及删除重复记录的SQL语句
一:查询及删除重复记录的SQL语句1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select * from peoplewhere peopleId in (select ...
- hdu 4597 + uva 10891(一类区间dp)
题目链接:http://vjudge.net/problem/viewProblem.action?id=19461 思路:一类经典的博弈类区间dp,我们令dp[l][r]表示玩家A从区间[l, r] ...
- ObCallback回调钩子检测
ObCallback回调钩子检测 2013-12-20 Nie.Meining Ring0 在 PatchGuard 的摧残下,通过 ObRegisterCallbacks 函数注册回调钩子已经成了 ...
- Callable接口、Runable接口、Future接口
1. Callable与Runable区别 Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理.Thread类.Runnable接口和Java内存管理模型使得多线 ...
- Struts2基本配置详解
Struts2配置文件加载顺序 struts2 配置文件由核心控制器加载 StrutsPrepareAndExecuteFilter (预处理,执行过滤) init_DefaultProperties ...
- MySQL数据库在WINDOWS系统CMD下的编码问题
MySQL数据库在WINDOWS系统CMD下的编码问题 1. 查看MySQL数据库编码 * SHOW VARIABLES LIKE 'char%'; 2. 编码解释 * character_set_c ...