JOISC2017 切符の手配题解

形式化题意:

给定正整数 n,mm 个三元组 (li,ri,ci),你有一个序列 a1n,初始所有元素为 0

你需要对序列 a 进行 m 次操作,对于第 i=1,,m 次操作,你需要:

  • 选择任意一个整数 k[0,ci]
  • 将所有 j0[li,ri]aj0 加上 k
  • 将所有 j1[1,li)(ri,n]aj1 加上 cik

请你最小化 maxai 的值。

思路:

推性质神仙题。

这道题,某些人通过猜结论,调着调着就过拍了,然后交上去过了。

不得不说,这道题的性质太妙了,感觉只能通过打表看出来……

Subtask 12

我们不妨先抛开 ci>1 的情况,只考虑 ci=1 时如何做。这样我们将问题转化成,初始每个区间都未反转,我们需要反转一些区间,使得操作后 maxai 尽可能地小。这里,我们定义反转一个区间 [li,ri] 为,将其对全集 [1,n] 取补,变为集合 [1,li)(ri,n]

多重集 S 为我们选出的需要反转的区间的集合,下文我们同时称 S 为一个反转方案。

性质 1:答案具有单调性。我们记答案的上界为 T。如果存在一种反转方案,使得 maxai=x,则对于所有 y(x,T],也存在一种反转方案使得 maxai=y

这说明,我们可以尝试用二分答案解决这个问题。

性质 2:若 S 中的所有区间之并为空,则这种反转方案一定不优。

证明:显然,此时存在区间 U1,U2S,满足 U1U2=,如果我们同时反转这两个区间,我们讨论反转后产生的贡献:

  • 所有 iU1U2ai 不变。
  • 所有 jU1U2aj 会加上 2

由于反转后没有 ai 会减少,所以这种反转方案不优。

也就是说,如果这 m 个区间存在一个子集有交,则存在一种最优方案,使得存在下标 tI,其中区间 I=[L,R]S 中的所有区间之并。

我们尝试二分答案 x。接下来我们讨论如何判定 x 是否合法。

我们记 pi 表示所有区间不反转时,所有操作进行完后 ai 的值,qi 表示对于当前集合 S,将 S 中的区间反转后,所有操作进行完后 ai 的值。记 zi=AS[iA],则 qi=pizi+|S|zi=pi+zt2zi。由于 qix,我们得到 pi+zt2zix。也就是说,要使得 x 合法,必须存在一个 S,使得通过其推导出的 zi 满足

zipi+ztx2

此时我们能够发现,如果我们确定了 tzt,则我们可以确定所有 zi(it) 的下界,即每个下标至少需要被 S 中的多少个区间覆盖。这时,找出一个满足条件的 S 也就变得容易了。

至此,我们可以通过枚举 tzt 的值,然后贪心地每次将 zi 取得尽量小。具体地,我们计算出每个 zi 的下界,然后依次遍历 i=1,,t,尝试将 zi 累加到下界(累加不到则当前 t,zt 不合法),每次取区间时,考虑从左端点小于等于 i 的区间中贪心地选出右端点最大的加入 S。遍历完后,只需检查 zi(t<in) 是否不小于下界即可。这样我们就设计出了一个判定 x 是否合法的朴素算法,外层再套一个二分即可得出答案。

注意,因为 tI,所以对于任意 1inzt 同时需要满足 pi+ztx2zizt,即 ztpix。也就是说,当 zt<pix 时我们可直接判定 zt 不合法。如果我们枚举 zt 时不从下界 maxpix 开始,并且在判定 x 是否合法时,仅仅只通过判定 zi 是否达到下界验证 x 的合法性,则算法的正确性无法保证。(想一想,为什么)

对于 ci=1 的情况,二分答案的时间为 O(logm),枚举 t,zt 的时间为 O(nm),贪心算法的时间为 O((n+m)logm),则总时间复杂度为 O(nm(n+m)log2m)

对于 ci>1 的情况,记 V=maxpi,则二分答案的时间为 O(logV),枚举 t,zt 的时间为 O(nV),贪心算法的时间不变(在代码中非常自然地改一下即可),则总时间复杂度为 O(nV(n+m)logmlogV)

这里给出贪心算法的代码:

// 所有变量名与之前约定的记号含义相同
// 所有三元组 (li,ri,ci) 都存储在 vec[li] 中
// 保证 zt 从下界 max(pi) - x 开始枚举
bool valid(long long x, int t, long long zt) {
for (int i = t + 1; i <= n; i ++) {
z[i] = 0;
}
std::priority_queue<Interval> q;
long long zi = 0;
for (int i = 1; i <= t; i ++) {
long long lim = (p[i] + zt - x + 1) >> 1;
for (int j = 0; j < vec[i].size(); j ++) {
if (vec[i][j].r > t) {
q.push(vec[i][j]);
}
}
while (q.size() && zi < lim) {
Interval iter = q.top();
q.pop();
int delta = std::min(lim - zi, (long long) iter.c);
zi += delta;
z[iter.r] -= delta;
if (iter.c -= delta) {
q.push(iter);
}
}
if (zi < lim) {
return false;
}
}
z[t] = zi;
for (int i = t + 1; i <= n; i ++) {
if (((z[i] += z[i - 1]) << 1) < p[i] + zt - x) {
return false;
}
}
return true;
}

其中 Interval 类和变量 vec 的定义如下:

class Interval {
public:
int l, r, c;
bool operator < (const Interval& rhs) const {
return r < rhs.r;
}
};
std::vector<Interval> vec[maxn];

比较明显的是,如果略去枚举 t,zt 的时间,总时间复杂度为 O((n+m)logmlogV),在该题目限制下可以接受。最优的 t,zt 只有 O(1) 种?或是说,我们只需要枚举 O(1)t,zt

Subtask 3

贪心算法的时间复杂度看起来已经不可优化了,我们尝试挖掘更多的性质,优化枚举 t,zt 的时间。

性质 3:存在一种最优方案,满足 |S|=0maxiIqimaxqi1

证明:我们假设命题不成立,并尝试推导出矛盾。根据条件,当前最优方案满足 maxiIqimaxqi2

首先我们证明,当前方案中不存在区间 US 使得 U=I

实际上,假设存在这样的区间,我们考虑将 US 中删除,即不翻转 U。记 S 为删除 U 后的多重集 Sqi 为删除 U 后的 qi。我们分析 qiqi 的关系:

  • 对于所有 iIqi=qi1
  • 对于所有 jIqj=qj+1

显然,qi 满足 x=argmaxqiI,则 qx=qx1。为了保证 S 的最优性,我们只好让 maxqiqx,由此可推导出 argmaxqiI,进而得到 maxqi=maxiIqi+1qx=maxqi,此与假设矛盾。因此,当前方案中不存在这样的区间。同时,我们可以得知当前方案中,S 中一定存在一个左端点为 L 的区间和一个右端点为 R 的区间(其中 I=[L,R],且这两个区间不同)。

现在,我们考虑以下调整算法:

  1. 如果当前 |S|2 或者已满足 maxiIqimaxqi1,结束调整。
  2. 否则,我们从 S 中分别选择一个左端点为 L 的区间和一个右端点为 R 的区间,然后将它们从 S 中删除。显然,这样调整后的方案仅仅只对于所有 iIqi 增加了 2,其它的 qi 不增,不劣于最优方案。然后我们回到步骤 1。

我们对当前方案进行以上调整算法,然后得到新的多重集 S0

若当前方案 S0 仍然有 maxiIqimaxqi2,一方面,我们容易知道 S0 满足 |S0|2;另一方面,我们在之前已经证明,若当前方案满足 maxiIqimaxqi2,则不存在区间 US0 使得 U=I,因此 |S0|1。综合这两方面,我们得知 |S0|=2

所以,我们仍然从 S0 中分别选择一个左端点为 L 的区间和一个右端点为 R 的区间,然后将它们从 S 中删除。容易知道这样的调整一定不劣于最优方案。调整后 |S0|=0,此与假设矛盾。

综上所述,命题成立。

这说明我们不需要大范围地枚举 zt 了。若当前位置 tI 存在最优方案满足 maxiIqimaxqi1,我们只需要判定 zt=ptxzt=ptx+1 两种情况中有其中一个合法即可。

总时间复杂度降至 O(n(n+m)logmlogV)

Subtask 45

既然我们优化掉了枚举 zt 的时间,那么 t 是不是也可以像 zt 一样,不需要枚举呢?我们随便猜一个结论然后跑一遍,可以发现:

性质 4:令 t=argmaxiIqi,若存在一种最优方案 S(|S|>0) 满足 qtmaxqi1,则 S 同时满足 pt=maxpi

证明:仍然考虑反证。若存在最优方案 S(|S|>0) 满足 qtmaxqi1,ptmaxpi1,则我们可推导出 x=argmaxpiI,因此 S 中至少存在一个区间没有覆盖到 x,即 zxzt1。我们得到

pxpt+1,zxzt1

注意到,qx=px2zx+zt,qt=ptzt,所以我们尝试对上述不等式做变换得到

px2zxpt2zt+3px2zx+ztptzt+3qxqt+3

此与假设条件 qtmaxqi1 矛盾。因此命题成立。

至此,我们又将 t 的范围缩小到 t{x|px=maxpi}

既然都到这一步了,我们继续猜测,是不是我们只要让 t 满足 pt=maxpi 就能够找到满足之前性质的最优解(找不到则 S= 为最优方案之一)?

性质 5:若存在一种最优方案 S(|S|>0) 满足 maxiIqimaxqi1,则 S 同时满足 {x|px=maxpi}I

证明:类似性质 4 的证明,我们考虑反证。令 t=argmaxiIqi,若当前最优方案 S 满足 qtmaxqi1,且存在 x 满足 xI,px=maxpi,则我们有

px=pt,zxzt1

综合上述不等式可得

px2zx+ztptzt+2qxqt+2

此与假设条件 qtmaxqi1 矛盾。因此命题成立。

据性质 5,我们可推断出,若存在一种最优方案 S(|S|>0) 满足 maxiIqimaxqi1,则对于所有 px=maxpixqx=pxzx 都相同(想一想,为什么)。所以,我们只需要令 t 为集合 {x|px=maxpi} 的其中一个元素,在二分时对于 (t,ptx)(t,ptx+1) 两种情况分别跑一遍贪心算法,即可做到判断当前答案 x 是否大于等于最优解。

总时间复杂度降至 O((n+m)logmlogV),足以通过此题。

posted @   December456  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示