题目可以看成一个最大流模型。源点 \(S\) 往所有机器人连边,容量为 \(c_i\);所有容器往汇点 \(T\) 连边,容量为 \(a_i\);机器人 \(i\) 往容器 \(j\in[l_i,r_i]\) 连边,容量 \(+\infty\)。最大流即为答案。
最大流不好计算,考虑最小割。不妨令选取容器集合为 \(S\),不被 \(S\) 包含的区间都必须割掉,于是代价为 \(\sum\limits_{x\in S}a_x+\sum\limits_{i=1}^m[[l_i,r_i]\nsubseteq S]c_i\) 。
这个可以考虑 dp,\(f_{i,j}\) 表示考虑前 \(i\) 个容器,最后一个未选的为 \(j\),最小代价。转移类似 AT_dp_w,可以线段树维护做到单次 \(O(n\log n)\)。
考虑 \(t_i=1\) 怎么算。可以发现,此时 \(S\) 可以表示为一个区间 \([L,R]\) 且满足 \(L\le x\le R\)。对 \(L\) 扫描线,维护历史 \(\min\) 即可。
现在存在 \(t_i=0\),仍然考虑取出 \(S\) 中极大的区间 \([L,R]\) 满足 \(L\le x\le R\)。那么代价可以拆成 \([1,L-1],[L,R],[R+1,n]\) 三个区间的贡献。前缀可以用上面的 dp 预处理 \(F_i\),后缀同理,记为 \(G_i\)。
中间部分考虑分讨 \(t=0\) 还是 \(1\):
- \(t_i=0\):\([l_i,r_i]\) 与 \([L,R]\) 有交且不被包含时被计入代价;
- \(t_i=1\):\([l_i,r_i]\) 只要不包含于 \([L,R]\) 即可。
这两个部分都可以扫描线,线段树维护历史 \(\min\),可以做到 \(O(n\log n)\)。
code
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
void file() {freopen("1.in", "r", stdin);freopen("1.out", "w", stdout);
}
using ll = long long;const ll kInfl = 1e18, kInf = 1e9;
const int kN = 2e5 + 5, kS = 1e6 + 5;int n, m;
array<int, kN> a;
array<ll, kN> prea, ans;struct Bot {int l, r, c, type;Bot() { }
};
array<Bot, kN> bot;namespace TYPE0 {namespace SGT {array<ll, kS> tag, mn;void clear() {fill_n(tag.data(), 4 * (n + 10), 0);fill_n(mn.data(), 4 * (n + 10), kInfl);}void pu(int o) { mn[o] = min(mn[ls], mn[rs]); }void ad(int o, ll v) { mn[o] += v; tag[o] += v; }void pd(int o) {if(ll& x = tag[o])ad(ls, x), ad(rs, x), x = 0;}void modify(int o, int l, int r, int x, ll v) {if(l == r) return void(mn[o] = v);pd(o); int mid = (l + r) >> 1;if(mid < x) modify(rs, mid + 1, r, x, v);else modify(ls, l, mid, x, v);pu(o);}void update(int o, int l, int r, int x, int y, ll v) {if((l > y) || (r < x)) return ;if((l >= x) && (r <= y)) return ad(o, v);pd(o); int mid = (l + r) >> 1;update(ls, l, mid, x, y, v);update(rs, mid + 1, r, x, y, v);pu(o);}ll query() { return mn[1]; }}array<ll, kN> F, G;void clear() {fill_n(F.data(), n + 2, kInfl);fill_n(G.data(), n + 2, kInfl);}void solvef() {sort(bot.data() + 1, bot.data() + m + 1, [&](Bot x, Bot y) { return x.r < y.r; });F[0] = 0;SGT::clear(), SGT::modify(1, 0, n, 0, 0);for(int i = 1, j = 1; i <= n; i++) {ll val = SGT::query();SGT::modify(1, 0, n, i, val);SGT::update(1, 0, n, 0, i - 1, a[i]);for(; (j <= m) && (bot[j].r == i); j++)if(!bot[j].type)SGT::update(1, 0, n, bot[j].l, i, bot[j].c);F[i] = SGT::query();}}void solveg() {sort(bot.data() + 1, bot.data() + m + 1, [&](Bot x, Bot y) { return x.l > y.l; });G[n + 1] = 0;SGT::clear(), SGT::modify(1, 1, n + 1, n + 1, 0);for(int i = n, j = 1; i; i--) {ll val = SGT::query();SGT::modify(1, 1, n + 1, i, val);SGT::update(1, 1, n + 1, i + 1, n + 1, a[i]);for(; (j <= m) && (bot[j].l == i); j++)if(!bot[j].type)SGT::update(1, 1, n + 1, i, bot[j].r, bot[j].c);G[i] = SGT::query();}}void solve() { clear(), solvef(), solveg(); }
}namespace TYPE_ALL {namespace A {array<ll, kN> dif;void clear() { fill_n(dif.data(), n + 1, 0); }void solve() {clear();ll sum1 = 0;for(int i = 1; i <= m; i++)if(bot[i].type) sum1 += bot[i].c;else {dif[bot[i].l] += bot[i].c;dif[bot[i].r + 1] -= bot[i].c;}for(int i = 1; i <= n; i++) dif[i] += dif[i - 1];for(int i = 1; i <= n; i++)ans[i] = dif[i] + sum1 + TYPE0::F[i - 1] + TYPE0::G[i + 1];}}namespace B {namespace SGT {struct Info {ll mn, h;Info() { mn = h = kInfl; }Info(ll _mn, ll _h) { mn = _mn; h = _h; }};Info operator + (const Info& x, const Info& y) {return Info(min(x.mn, y.mn), min(x.h, y.h));}struct Tag {ll a00, a01, a11;Tag() { a00 = a11 = 0; a01 = kInfl; }Tag(ll _a00, ll _a01, ll _a11) {a00 = _a00; a01 = _a01; a11 = _a11;}bool empty() { return !a00 && !a11 && (a01 == kInfl); }};Tag& operator += (Tag& x, const Tag& y) {Tag ans;ans.a00 = x.a00 + y.a00;ans.a01 = min(x.a00 + y.a01, x.a01 + y.a11);ans.a11 = x.a11 + y.a11;return x = ans;}Info& operator += (Info& x, const Tag& y) {x.h = min(x.mn + y.a01, x.h + y.a11);x.mn += y.a00;return x;}array<Info, kS> sum;array<Tag, kS> tag;void clear() {fill_n(sum.data(), 4 * (n + 10), Info());fill_n(tag.data(), 4 * (n + 10), Tag());}void pu(int o) { sum[o] = sum[ls] + sum[rs]; }void build(int o, int l, int r, ll* val) {if(l == r)return void(sum[o] = Info(val[l], val[l]));int mid = (l + r) >> 1;build(ls, l, mid, val);build(rs, mid + 1, r, val);pu(o);}void ad(int o, const Tag& t) { sum[o] += t; tag[o] += t; }void pd(int o) {if(!tag[o].empty())ad(ls, tag[o]), ad(rs, tag[o]), tag[o] = Tag();}void update(int o, int l, int r, int x, int y, Tag t) {if((l > y) || (r < x)) return ;if((l >= x) && (r <= y)) return ad(o, t);pd(o); int mid = (l + r) >> 1;update(ls, l, mid, x, y, t);update(rs, mid + 1, r, x, y, t);pu(o);}ll query(int o, int l, int r, int x, int y) {if((l > y) || (r < x)) return kInfl;if((l >= x) && (r <= y)) return sum[o].h;pd(o); int mid = (l + r) >> 1;return min(query(ls, l, mid, x, y), query(rs, mid + 1, r, x, y));}void add(int l, int r, ll v) { update(1, 1, n, l, r, Tag(v, kInfl, 0)); }void updateh() { ad(1, Tag(0, 0, 0)); }}array<ll, kN> val;array<vector<int>, kN> buc0L, buc0R, buc1;void clear() {SGT::clear();fill_n(val.data(), n + 1, 0);fill_n(buc0L.data(), n + 1, vector<int> ());fill_n(buc0R.data(), n + 1, vector<int> ());fill_n(buc1.data(), n + 1, vector<int> ());}void init() {for(int i = 1; i <= m; i++) {if(!bot[i].type) {if(bot[i].l != bot[i].r) {val[bot[i].l] += bot[i].c;val[bot[i].r] -= bot[i].c;buc0L[bot[i].l].push_back(i);buc0R[bot[i].r].push_back(i);}}else {val[1] += bot[i].c;val[bot[i].r] -= bot[i].c;buc1[bot[i].l].push_back(i);}}for(int i = 1; i <= n; i++) val[i] += val[i - 1];for(int i = 1; i <= n; i++)val[i] += prea[i] + TYPE0::G[i + 1];SGT::build(1, 1, n, val.data());}void solve() {clear(), init();for(int i = 1; i <= n; i++) {ans[i] = min(ans[i], SGT::query(1, 1, n, i, n));SGT::add(i + 1, n, -a[i]);for(int j : buc0L[i]) SGT::add(bot[j].r, n, bot[j].c);for(int j : buc0R[i]) SGT::add(i + 1, n, -bot[j].c);for(int j : buc1[i]) SGT::add(bot[j].r, n, bot[j].c);SGT::add(i + 1, n, TYPE0::F[i] - TYPE0::F[i - 1]);SGT::updateh();}}}void solve() { A::solve(), B::solve(); }
}void solve() {cin >> n >> m;for(int i = 1; i <= n; i++)cin >> a[i], prea[i] = prea[i - 1] + a[i];for(int i = 1; i <= m; i++)cin >> bot[i].l >> bot[i].r >> bot[i].c >> bot[i].type;TYPE0::solve(), TYPE_ALL::solve();for(int i = 1; i <= n; i++)cout << ans[i] << " \n" [i == n];
}int main() {// file();ios::sync_with_stdio(0), cin.tie(0);int T = 1;cin >> T;while(T--) solve();return 0;
}