@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的更多相关文章

  1. 「JOISC 2019 Day4」蛋糕拼接 3

    loj 3039 NKOJ Description \(n\)个蛋糕,每个蛋糕有\(w_i,h_i\).选\(m\)个蛋糕满足\(\sum\limits_{j=1}^mw_{k_j}-\sum\lim ...

  2. LOJ#2882. 「JOISC 2014 Day4」两个人的星座(计算几何)

    题面 传送门 题解 我们发现如果两个三角形相离,那么这两个三角形一定存在两条公切线 那么我们可以\(O(n^2)\)枚举其中一条公切线,然后可以暴力\(O(n^3)\)计算 怎么优化呢?我们可以枚举一 ...

  3. 【LOJ】#3036. 「JOISC 2019 Day3」指定城市

    LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...

  4. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  5. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

  6. 【LOJ】#3033. 「JOISC 2019 Day2」两个天线

    LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...

  7. 【LOJ】#3031. 「JOISC 2019 Day1」聚会

    LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...

  8. 【LOJ】#3030. 「JOISC 2019 Day1」考试

    LOJ#3030. 「JOISC 2019 Day1」考试 看起来求一个奇怪图形(两条和坐标轴平行的线被切掉了一个角)内包括的点个数 too naive! 首先熟练的转化求不被这个图形包含的个数 -- ...

  9. 「JOISC 2019 Day3」穿越时空 Bitaro

    「JOISC 2019 Day3」穿越时空 Bitaro 题解: ​ 不会处理时间流逝,我去看了一眼题解的图,最重要的转换就是把(X,Y)改成(X,Y-X)这样就不会斜着走了. ​ 问题变成二维平面上 ...

随机推荐

  1. SPSS正交设计的操作

    SPSS正交设计的操作 设要做二因素的正交设计,A因素有三个水平,B因素有两个水平.则选择Data-->Orthogonal Design-->generate,弹出的就是正交设计窗口: ...

  2. HDU4578 Transformation (多操作线段树)

    传送门 终于过了这道题.. 要注意标记之间的影响,和add操作时更新求和的顺序. same 区间每个数设置为x标记 mult  区间每个数乘x标记 add  区间每个数加x标记 ①:当打same标记时 ...

  3. java验证码识别

    首先参考了csdn大佬的文章,但是写的不全ImgUtils类没有给出代码,无法进行了 写不完整就是制造垃圾 不过这个大佬又说这个大佬的文章值得参考于是又查看这篇文章 有案例https://blog.c ...

  4. 【CODEVS】2833 奇怪的梦境

    2833 奇怪的梦境 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description Aiden陷入了一个奇怪的梦境:他被困在一个小房子中,墙上有很 ...

  5. 未加星标 ajax三级联动的实现方法

    <div id="sanji"></div> 下面考虑的是要有省市区这三列,这三列用的是下拉列表,那么里面要用<option></opti ...

  6. 【CS Round #44 (Div. 2 only) B】Square Cover

    [链接]点击打开链接 [题意] 给你一个n*m的矩形,让你在其中圈出若干个子正方形,使得这些子正方形里面的所有数字都是一样的. 且一样的数字,都是在同一个正方形里面.问你有没有方案. [题解] 相同的 ...

  7. 【CRT相关配置】

    1.选项——会话选项 2.回话调整如下: 3.日志文件记录保存,即保存所有输入的命令 文件名:%S-%T-%M-%D.txt,表示每天会存放到一个文件 选择:在连接上启动记录 和  追加到文件

  8. 【Pyqt5】之高级控件QTableWidget的使用

    1:动态渲染数据+动态添加控件(按钮,进度条) class MainWindow(QWidget, Ui_MainFrom): def __init__(self): super(MainWindow ...

  9. docker容器时区问题

    原文:docker容器时区问题 版权声明:本文为博主原创文章,随意转载. https://blog.csdn.net/Michel4Liu/article/details/80890868 本系列目录 ...

  10. NodeJs的简介及安装

    首先 分享一下NodeJs的应用场景吧: Web聊天室(IM):Express + Socket.io socket.io一个是基于Nodejs架构体系的,支持websocket的协议用于时时通信的一 ...