反重力系统

题目背景

你有一块反重力的巨大磁铁。

题目描述

你有 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] 流量为 inf⁡inf,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∑m​ci​−i=l+1∑r−1​ci​−i=1∑n​ai​+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)log⁡m)O((n+m)logm) 次,另一颗线段树支持区间加、区间 querymaxquerymax O((n+m)log⁡m)O((n+m)logm) 次,复杂度是 O((n+m)log⁡2m)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 定理形式与最小割几乎类似,就留给读者细究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值