题目背景
你有一块反重力的巨大磁铁。
题目描述
你有 nn 种铁钉和 mm 个磁铁。第 ii 种铁钉有 aiai 个,只能被编号在 [li,ri][li,ri] 内的磁铁吸引。为了不让磁铁消失磁力,第 ii 个磁铁最多只能吸引 cici 个铁钉。
但是你有一个反重力引擎。具体地,假设你把引擎安装在了磁铁 kk 处(反重力引擎不会让 ckck 减少),那么一种原先被 [L,R][L,R] 内磁铁吸引的铁钉可以被 [min(L,k),max(R,k)][min(L,k),max(R,k)] 内的所有磁铁吸引。
因为你不想让铁钉把你的仓库堆满,你想知道对于所有 kk 取 1∼n1∼n 的值,最多能有多少枚铁钉被吸引。
输入格式
本题有多组数据。
第一行,一个整数 TT,表示数据组数。对于每组数据:
- 第一行两个整数 m,nm,n。
- 接下来一行 mm 个整数 c1…cmc1…cm。
- 接下来 nn 行,每行三个整数 li,ri,aili,ri,ai。
输出格式
对于每组数据,一行 mm 个整数,分别表示 kk 取 1∼m1∼m 的答案。
样例
输入数据 1
2
4 3
3 3 2 2
1 2 2
3 3 3
2 2 4
5 1
1 2 3 4 5
1 1 17
输出数据 1
8 7 7 9
1 3 6 10 15
数据规模与约定
本题采用子任务捆绑测试,可能轻微卡常(但是保证开了 2.52.5 倍时限以上)。
- Subtask 0(25 pts):∑n≤80∑n≤80,∑m≤80∑m≤80。
- Subtask 1(15 pts):∑n≤500∑n≤500,∑m≤500∑m≤500。
- Subtask 2(10 pts):∑n≤104∑n≤104,∑m≤80∑m≤80。
- Subtask 3(50 pts):无特殊限制。
对于 Subtask 0~2 时间限制为 11 秒,Subtask 3 时间限制为 55 秒。
对于 100%100% 的数据,保证 1≤∑n,∑m≤1051≤∑n,∑m≤105,1≤ai,bi≤1091≤ai,bi≤109,1≤li≤ri≤n1≤li≤ri≤n。
题解
让我们重新表述一下这个问题:构建一个网络流模型,s→is→i 流量为 aiai,i→[li+n,ri+n]i→[li+n,ri+n] 流量为 infinf,i+n→ti+n→t 流量为 cici。
要求改变区间后,对每个 xx 求出最大流。
回忆 Hall 定理:
- 一个二分图对右部点有完美匹配,当且仅当对于任何右部点集合 SS 满足 ∣N(S)∣≥∣S∣∣N(S)∣≥∣S∣;
- 推广:一个带权二分图对右部点有带权完美匹配,当且仅当对于任何右部点集合 SS 满足 Val(N(S))≥Val(S)Val(N(S))≥Val(S)。
设 X=Val(S)X=Val(S),Y=Val(N(S))Y=Val(N(S))。此处的完美匹配就是 ∑ci∑ci。由于 Hall 定理只给出了完美匹配的标准,我们必须修改它让它能够计算最大流。比如说,增加一个能被所有磁铁匹配的权值为 ss 的铁钉,那么:只要 X≤Y+sX≤Y+s,我们就能断言最大流的值,因此我们只要找到 s=max(X−Y)s=max(X−Y)(再次注意,XX 是磁铁,而 YY 是铁钉)。
固定 YY,我们想要最大化 XX,可以加入所有使 YY 不变的磁铁,那么对于 1≤l≤x≤r≤n1≤l≤x≤r≤n,如果 ≤x≤x 的磁铁编号最大为 ll,≥x≥x 的磁铁编号最小为 rr,那么显然可以加入 [1,l]∪[r,n][1,l]∪[r,n] 的所有磁铁。
令 c[L,R]c[L,R] 表示 cL+cL+1+⋯+cRcL+cL+1+⋯+cR,a[L,R]a[L,R] 表示 L≤li≤ri≤RL≤li≤ri≤R 的铁钉的 aiai 之和。固定 l,rl,r,显然
X−Y=∑i=1mci−∑i=l+1r−1ci−∑i=1nai+a[l+1,r−1]X−Y=i=1∑mci−i=l+1∑r−1ci−i=1∑nai+a[l+1,r−1]
删去容易计算的常量,我们只考虑 a[l+1,r−1]−c[l+1,r−1]a[l+1,r−1]−c[l+1,r−1],也就是 a[l,r]−c[l,r]a[l,r]−c[l,r]。排除掉平凡的情况(如果 l=xl=x 或 r=xr=x,我们事实上相当于可以加入所有的 XX 和所有的 YY),我们只考虑用 a[l,r]−c[l,r]a[l,r]−c[l,r] 对 l≤x≤rl≤x≤r 的所有 xx 快速 chkmaxchkmax。
我们采用分治的方式解决上述问题。让我们设 solve(L,R)solve(L,R) 表示解决 L≤l≤r≤RL≤l≤r≤R 的所有问题。
首先,取 M=⌊L+R2⌋M=⌊2L+R⌋ 并递归解决。然后我们便只关心 L≤l≤ML≤l≤M,M+1≤r≤RM+1≤r≤R 的问题。显然这个问题对于 x≤Mx≤M 和 x≥M+1x≥M+1 又不同了,如果仅考虑 x≤Mx≤M:显然 rr 一端的后缀我们只要取一个最大值即可,线段树维护,于是扫描一下 ll。另一侧同理。
需要一颗线段树支持区间 chkmaxchkmax O((n+m)logm)O((n+m)logm) 次,另一颗线段树支持区间加、区间 querymaxquerymax O((n+m)logm)O((n+m)logm) 次,复杂度是 O((n+m)log2m)O((n+m)log2m) 的。
std::vector<std::pair<int, int>> Rp[MAXN], Lp[MAXN];
void dc_L(int l, int r) {
if (l == r) { for (auto [r, v] : Rp[l]) T2::add(r, N, v); T1::chkmax(l, l, T2::query(l, l) + s[l - 1]); return; }
int mid = l + r >> 1; dc_L(mid + 1, r);
for (int k = mid; k >= l; --k) {
for (auto [r, v] : Rp[k]) T2::add(r, N, v);
long long val = T2::query(mid + 1, r) + s[k - 1];
T1::chkmax(k, mid, val);
}
for (int k = l; k <= mid; ++k) for (auto [r, v] : Rp[k]) T2::add(r, N, -v);
dc_L(l, mid);
}
void dc_R(int l, int r) {
if (l == r) { for (auto [l, v] : Lp[r]) T2::add(1, l, v); T1::chkmax(r, r, T2::query(r, r) - s[r]); return; }
int mid = l + r >> 1; dc_R(l, mid);
for (int k = mid + 1; k <= r; ++k) {
for (auto [l, v] : Lp[k]) T2::add(1, l, v);
long long val = T2::query(l, mid) - s[k];
T1::chkmax(mid + 1, k, val);
}
for (int k = mid + 1; k <= r; ++k) for (auto [l, v] : Lp[k]) T2::add(1, l, -v);
dc_R(mid + 1, r);
}
可以通过限制区间范围和减少区间撤销、减少 chkmaxchkmax 操作等方式来卡常(在上述代码中没有展示出来,请选手各显神通)。
这里的 Hall 定理形式与最小割几乎类似,就留给读者细究。