@loj - 3039@ 「JOISC 2019 Day4」蛋糕拼接 3
@description@
今天是 IOI 酱的生日,所以她的哥哥 JOI 君给她预定了一个生日蛋糕。虽然他计划买一整个蛋糕,但是他不小心订成了
N
块蛋糕。这
N
块蛋糕编号为
1\ldots N
,每块蛋糕都有价值和颜色。第
i
块蛋糕的价值为
V_i
,颜色深度为
C_i
。
为了做成一整块蛋糕,他决定选择
M
块互不相同的蛋糕,然后将它们按一定顺序排成一个环。整块蛋糕的美观程度定义如下:
\sum_{j=1}^M V_{k_j}-\sum_{j=1}^M|C_{k_j}-C_{k_{j+1}}|
其中,他选择了编号为
k_1,\ldots ,k_M
的蛋糕(这里令
k_{M+1}=k_1
)。换句话说,整个蛋糕的美观程度为选择蛋糕的价值和与所有相邻两块蛋糕颜色深度差的绝对值之和的差。JOI 君想要让整块蛋糕尽可能美观。
写一个程序,在给定蛋糕的块数,选择蛋糕的数目和每块蛋糕的价值和颜色深度的情况下,计算 JOI 君做成的蛋糕的最大美观度。
@solution@
首先考虑选定蛋糕后,如何编排美观度最大,因为编排只会影响 \(-\sum_{j=1}^{M}|C_{k_j} - C_{k_{j+1}}|\) 的大小,所以只需要它最大即可。
考虑每个 C 的贡献,可以将上式写作 \(-\sum_{j=1}^{M}(a_j + b_j)*C_{k_j}\),其中 \(a_j, b_j\) 为 1 或 -1,是通过拆绝对值得到的。
由于 a, b 是拆绝对值得到的,所以最大值对应的 a = b = 1,最小值对应的 a = b = -1;同时 ∑(a+b) = 0。
我们可以证明,除最大值与最小值以外,其他数取 a = 1, b = -1 最优。假如更改一个数的 b = 1,则必然有一个比它小的数的 a 更改为 -1,而这是不优的。
所以可以等价地转为使 \(\sum_{j=1}^{M}V_{k_j} - 2*(\max\{C_{k_j}\} - \min\{C_{k_j}\})\) 最大。
考虑将所有蛋糕按 C 排序。然后我们去枚举最大值的上界 C[r] 和最小值的下界 C[l](如果是枚举最大值则要保证那个值必须选择,后面的处理就不大方便)。
则我们选择的 M 块蛋糕要在区间 [l, r] 中选择。因为 C 已经固定,我们需要 V 的和最大,显然是选择区间内前 M 大的 V 求和。
则一个区间 [l, r] 的贡献 = 区间内 V 值前 M 大之和 - 2*(C[r] - C[l])。枚举区间并计算需要 O(n^2*logn) 的时间复杂度。
然后考虑优化。我们可以从决策单调性的方面入手。因为考虑了一会儿发现没啥地方可以下手的,于是生成一点随机数据打个表惊讶地发现它有决策单调性。
如果知道了它有决策单调性,用单调栈+二分或者分治找决策点都可以,用可持久化权值线段树计算,时间复杂度降为 O(n*log^2n)。
大概感性证明一下单调性。我们只需要证明如果 p < q <= i 且区间 [q, i] 优于 [p, i],则区间 [q, i+1] 优于 [p, i+1]。
记 f(l, r) 表示区间 [l, r] 内 V 值前 M 大之和。由题设可得 f(q, i) - 2*(C[i] - C[q]) >= f(p, i) - 2*(C[i] - C[p]),即 f(q, i) - f(p, i) >= 2*C[p] - 2*C[q]。
因为 f(l, r) 有一个性质:对于 p < q <= i,有 f(q, i+1) - f(q, i) >= f(p, i+1) - f(p, i)。这个性质直观上感知不难,详细证明需要讨论区间 [p, i], [q, i] 中的最小值与 V[i+1] 的关系。
于是 f(q, i+1) - f(p, i+1) >= f(q, i) - f(p, i) >= 2*C[p] - 2*C[q],从而得到结论 f(q, i+1) - 2*(C[i+1] - C[q]) >= f(p, i+1) - 2*(C[i+1] - C[p])。
@accepted code@
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 200000;
const ll INF = (1LL<<60);
struct segtree{
struct node{
node *ch[2];
int cnt; ll sum;
}pl[20*MAXN + 5], *rt[MAXN + 5], *ncnt, *NIL;
segtree() {rt[0] = ncnt = NIL = &pl[0]; NIL->ch[0] = NIL->ch[1] = NIL;}
node *insert(node *pre, int l, int r, int p, ll k) {
node *nw = (++ncnt); (*nw) = (*pre);
nw->cnt++, nw->sum += k;
if( l == r ) return nw;
int mid = (l + r) >> 1;
if( p <= mid ) nw->ch[0] = insert(pre->ch[0], l, mid, p, k);
else nw->ch[1] = insert(pre->ch[1], mid + 1, r, p, k);
return nw;
}
ll query(node *L, node *R, int p) {
if( !p ) return 0;
if( R->ch[0] == NIL && R->ch[1] == NIL )
return R->sum/R->cnt*p;
if( R->ch[1]->cnt - L->ch[1]->cnt > p )
return query(L->ch[1], R->ch[1], p);
else
return query(L->ch[0], R->ch[0], p - (R->ch[1]->cnt - L->ch[1]->cnt)) + R->ch[1]->sum - L->ch[1]->sum;
}
}T;
struct cake{
int V, C;
friend bool operator < (cake a, cake b) {
return a.C < b.C;
}
}ck[MAXN + 5];
int N, M;
ll get_ans(int l, int r) {
return T.query(T.rt[l-1], T.rt[r], M) - 2*(ck[r].C - ck[l].C);
}
ll ans = -INF; int pnt[MAXN + 5];
int get_point(int l, int r, int x) {
int p = l; ll k = get_ans(p, x);
for(int i=l+1;i<=r&&x-i+1>=M;i++) {
ll q = get_ans(i, x);
if( q > k )
p = i, k = q;
}
ans = max(ans, k);
return pnt[x] = p;
}
void solve(int L, int R, int le, int ri) {
if( L > R ) return ;
int mid = (L + R) >> 1, p = get_point(le, ri, mid);
solve(L, mid - 1, le, p);
solve(mid + 1, R, p, ri);
}
int d[MAXN + 5], dcnt = 0;
int main() {
scanf("%d%d", &N, &M);
for(int i=1;i<=N;i++)
scanf("%d%d", &ck[i].V, &ck[i].C), d[++dcnt] = ck[i].V;
sort(ck + 1, ck + N + 1);
sort(d + 1, d + dcnt + 1), dcnt = unique(d + 1, d + dcnt + 1) - d - 1;
for(int i=1;i<=N;i++)
T.rt[i] = T.insert(T.rt[i-1], 1, N, lower_bound(d + 1, d + dcnt + 1, ck[i].V) - d, ck[i].V);
solve(M, N, 1, N - M + 1);
printf("%lld\n", ans);
}
@details@
好久没有写可持久化权值线段树求第 k 大(我写过吗),结果没有处理好存在相同的值的时候怎么办。。。WA 了好几发。。。
然后就是注意区间 [l, r] 的长度必须 >= M,不然也会 WA。。。
@loj - 3039@ 「JOISC 2019 Day4」蛋糕拼接 3的更多相关文章
- 「JOISC 2019 Day4」蛋糕拼接 3
loj 3039 NKOJ Description \(n\)个蛋糕,每个蛋糕有\(w_i,h_i\).选\(m\)个蛋糕满足\(\sum\limits_{j=1}^mw_{k_j}-\sum\lim ...
- LOJ#2882. 「JOISC 2014 Day4」两个人的星座(计算几何)
题面 传送门 题解 我们发现如果两个三角形相离,那么这两个三角形一定存在两条公切线 那么我们可以\(O(n^2)\)枚举其中一条公切线,然后可以暴力\(O(n^3)\)计算 怎么优化呢?我们可以枚举一 ...
- 【LOJ】#3036. 「JOISC 2019 Day3」指定城市
LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...
- 【LOJ】#3034. 「JOISC 2019 Day2」两道料理
LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...
- 【LOJ】#3032. 「JOISC 2019 Day1」馕
LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...
- 【LOJ】#3033. 「JOISC 2019 Day2」两个天线
LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...
- 【LOJ】#3031. 「JOISC 2019 Day1」聚会
LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...
- 【LOJ】#3030. 「JOISC 2019 Day1」考试
LOJ#3030. 「JOISC 2019 Day1」考试 看起来求一个奇怪图形(两条和坐标轴平行的线被切掉了一个角)内包括的点个数 too naive! 首先熟练的转化求不被这个图形包含的个数 -- ...
- 「JOISC 2019 Day3」穿越时空 Bitaro
「JOISC 2019 Day3」穿越时空 Bitaro 题解: 不会处理时间流逝,我去看了一眼题解的图,最重要的转换就是把(X,Y)改成(X,Y-X)这样就不会斜着走了. 问题变成二维平面上 ...
随机推荐
- LintCode 两两交换链表中的节点
给一个链表,两两交换其中的节点,然后返回交换后的链表. 样例 给出 1->2->3->4, 你应该返回的链表是 2->1->4->3. 分析:第一次调试的时候用了P ...
- bzoj3064/洛谷P4314 CPU监控【线段树】
好,长草博客被催更了[?] 我感觉这题完全可以当作线段树3 线段树2考加法和乘法标记的下放顺序,这道题更丧心病狂[?] 很多人可能跟我一样,刚看到这道题秒出思路:打一个当前最大值一个历史最大值不就完事 ...
- Excel怎么增加撤销操作的次数?Excel增加可撤销次数教程
Excel怎么增加撤销操作的次数?Excel增加可撤销次数教程 在Excel的使用中,返回上一步是经常用到的一个工具,当数据填写有误需要查看之前的内容时,一般会通过"Ctrl Z" ...
- font-family:黑体;导致css定义全部不起作用
css文件里font-family: "黑体";这句会导致后面的css定义全部不起作用了. 只要把font-family: "黑体"; 改成 font-fami ...
- 关于Python缩进,我们该了解哪些?
Python是一门独特的语言,它的代码块是通过缩进(Indentation)来标记的(大部分语言都是使用花括号作为代码块的标记),具有相同缩进的多行代码属于同一个代码块.如果代码莫名其妙的乱缩进,Py ...
- React map生成元素添加点击事件绑定this
问题 使用.map(function(Item)生成元素添加onClick事件:onClick={this.provinceChange.bind(this, "99")}时,前台 ...
- Leetcode929.Unique Email Addresses独特的电子邮件地址
每封电子邮件都由一个本地名称和一个域名组成,以 @ 符号分隔. 例如,在 alice@leetcode.com中, alice 是本地名称,而 leetcode.com 是域名. 除了小写字母,这些电 ...
- 如何在liferay 7 mvc-portlet中调用service-builder项目生成的service
不想写了,贴大神帖子 https://web.liferay.com/web/zhao.jin/blog/-/blogs/creating-service-builder-mvc-portlet-in ...
- QLabel添加Click信号
使用自定义label来实现此功能 其他控件可参照此例. #include "customerqlabel.h" CustomerQlabel::CustomerQlabel(QWi ...
- R是用于统计分析、绘图的语言和操作环境
R是一套完整的数据处理.计算和制图软件系统.其功能包括:数据存储和处理系统:数组运算工具(其向量.矩阵运算方面功能尤其强大):完整连贯的统计分析工具:优秀的统计制图功能:简便而强大的编程语言:可操纵数 ...