HTP10590 只為一人封刀 題解——2025.9.25 鮮花
HTP10590 只為一人封刀 題解
サワーチェリーが輝いたから + 弦楽少女は諦めを知らずに = 幕を下ろそう、パレードへ
本段落中所使用的歌詞,其著作權(quán)屬于原著作權(quán)人,僅以介紹為目的引用。
因為那顆酸櫻桃閃閃發(fā)光? 弦樂少女不知何謂放棄?
以上是賀的萌娘百科
以下也是



感覺牛炸了,各種意義上
感覺是好題。
暴力網(wǎng)絡流是顯。
定義寶石是左部點集合 \(|A|\),劍是右部點集合 \(|B|\)。
首先典的考慮 Hall 定理:最大流是 \(\sum_{i = 1} ^ n a_i - \max_{S}\{|S| - |{\rm N}(S)|\}\),\(S \subseteq B\) 是右部點的集合,\({\rm N}(S)\) 是 \(S\) 所連的左部點。
我們考慮 \(type_i = 1\) 怎么做,先固定 \(x\),此時我們所有區(qū)間都包含 \(x\) 這個點,此時我們發(fā)現(xiàn)我們可以輕松欽定所有 \(L \le l_i \le x \le r_i \le R\) 的寶石 \(i\) 不選,考慮這時我們盡量多的選右部點,我們發(fā)現(xiàn)我們可以選的是 \(<l\) 和 \(>r\) 的前后綴。
簡單推一下式子,我們要對所有 \(L \le x \le R\) 求:
去除容易計算的常量,我們要求的是
考慮分治,設當前是 Solve(l, r) : mid = (l + r) / 2,我們只需要處理所有 \(l \le L \le mid < R \le r\) 的 \([L, R]\) 對 \(x\in [L, R]\) 的貢獻。
我們直接掃描 \(L\) 并用線段樹維護 \(\max R\) 并另外維護 \(x \in [L, mid]\) 的 checkmax 即可,對 \(R\) 同理。
考慮怎么做 \(type_i = 0\)。
首先對于所有 \(L \le l_i \le r_i \le R\) 的區(qū)間顯然是選不上的,我們直接和 \(type_i = 1\) 的一起處理。
我們先欽定其他所有的 \(type_i = 0\) 的寶石都選上,現(xiàn)在我們考慮選上一些區(qū)間,這樣我們就要減掉一些 \(b_i\) 并減掉其對應的一些 \(a_i\) 的貢獻。
我們發(fā)現(xiàn)對于 \(l_i \le L - 1 \le r_i \le R\) 的貢獻我們會在 \(L' = l_i\) 的 \([L', R]\) 中統(tǒng)計到,這樣我們其實最后只需要考慮 \(r - 1 < L\) 和 \(R + 1 < l\) 的部分,同時因為和 \([L, R]\) 之間至少隔著一個點所以也不會對 \(type_i = 1\) 的點產(chǎn)生貢獻。
于是問題就變成了一個前后綴問題,我們直接 dp,設 \(f_i\) 表示 \(i\) 前綴的貢獻,\(g_i\) 表示 \(i\) 后綴的貢獻。我們考慮 \(f_i\) 的轉(zhuǎn)移方程:
道理就是枚舉一個后綴的 \(a\) 全部扔掉,\(g\) 同理。
這個 dp 顯然直接掃描線加線段樹優(yōu)化一下直接就做完了,最后我們 checkmax 的東西就是
注意最后我們要對每個 \(x\) checkmax \(f_x + g_{x + 1}\),別忘了用 \(\sum b\) 減。
\(n, m\) 同階,復雜度 \({\cal O}(n \log^2 n)\)。
能不能再給力一點啊!
發(fā)現(xiàn)復雜度上界是 \(type_i = 1\) 的分治上線段樹,這能忍住不優(yōu)化到線段樹分治?
我們考慮分治的過程中我們干了什么,考慮 Solve(l, r) : mid = (l + r) / 2 的掃描 \(L\) 的過程,\(R\) 同理。
首先 checkmax 可以直接一個前綴 \(\max\) 狀物 \({\cal O}(mid - l + 1)\) 做。
我們發(fā)現(xiàn)首先我們需要將所有 \(mid < l_i \le r_i \le r\) 的 \(b_i\) 加上,這個操作我們在 Solve(mid + 1, r) 時干了。
然后我們對于所有 \(l_i = L, r_i \le r\) 的區(qū)間,我們要貢獻 \(b_i\)。考慮貢獻,我們事實上是 \([\max\{b_i, mid + 1\}, r]\) 的區(qū)間加。
并且還有 \(mid - l + 1\) 次 \([mid + 1, r]\) 求 \(\max\)。
我們直接在線段樹上跑,這樣 \([mid + 1, r]\) 在線段樹上是一個節(jié)點,單次查詢是 \({\cal O}(1)\) 的,對于修改,我們發(fā)現(xiàn)若 \(b_i <= mid\),\([mid + 1, r]\) 的區(qū)間加依然是 \({\cal O}(1)\) 的,而對于所有區(qū)間,其剩下的貢獻都只有一次,即只會在 \(l \le l_i \le mid < r_i \le r\) 的 Solve(l, r) 中貢獻,總次數(shù)是 \({\cal O}(m)\) 的,這部分的復雜度依然是 \({\cal O}(m\log n)\) 的。
我們認為 \(n, m\) 同階,復雜度就是 \({\cal O}(n \log n)\) 的了。
我代碼中 df[i] 是 \(-f_i\),dg 是 \(-g_i\)。
Code
/*
ulimit -s 1024000 && clear && g++ % -o %< -O2 -std=c++14 -DLOCAL -Wall -Wextra && ulimit -v 128000 && ./%<
ulimit -s 1024000 && clear && g++ % -o %< -O2 -std=c++14 -DLOCAL -Wall -Wextra -fsanitize=address,undefined -g && ./%<
echo && cat out.out && echo
*/
#include <bits/stdc++.h>
using namespace std;
using llt = long long;
using llf = long double;
using ull = unsigned long long;
#define endl '\n'
#ifdef LOCAL
FILE *InFile = freopen("in.in", "r", stdin), *OutFile = freopen("out.out", "w", stdout);
#endif
const int N = 2e5 + 3;
const llt Inf = 0x3f3f3f3f3f3f3f3fll;
int n, m, _a[N]; llt qa[N], aas[N], df[N], dg[N];
vector<pair<int, int>> pla[N], pra[N], plb[N], prb[N];
#define lson (t << 1)
#define rson (t << 1 | 1)
#define mid ((l + r) >> 1)
class Seg{
private:
static const int D = N << 2;
llt nd[D], tg[D]; function<llt(llt, llt)> F;
void add(llt v, int t){ nd[t] += v, tg[t] += v; }
void Dwn(int t){ if(llt &x = tg[t]) add(x, lson), add(x, rson), x = 0; }
void Upd(int t){ nd[t] = F(nd[lson], nd[rson]); }
public:
Seg(const auto &f) : F(f){}
void Add(int L, int R, llt v, int l = 1, int r = n, int t = 1){
if(l == L && r == R) return add(v, t), void();
Dwn(t);
if(R <= mid) Add(L, R, v, l, mid, lson);
else if(L > mid) Add(L, R, v, mid + 1, r, rson);
else Add(L, mid, v, l, mid, lson), Add(mid + 1, R, v, mid + 1, r, rson);
Upd(t);
}
llt Get(){ return nd[1]; }
void Clr(){ memset(nd, 0, sizeof nd), memset(tg, 0, sizeof tg); }
friend void Cdq(int, int, int);
} pre([](llt a, llt b){ return a < b ? a : b; }),
nxt([](llt a, llt b){ return a > b ? a : b; }),
seg([](llt a, llt b){ return a < b ? a : b; });
llt tp[N];
void Cdq(int l = 1, int r = n, int t = 1){
if(l == r){
llt s = 0; pre.nd[t] = -qa[l - 1] + df[l - 1], nxt.nd[t] = -qa[l] - dg[r + 1];
for(auto [nr, v] : plb[l]) if(nr == r) pre.add(-v, t), nxt.add(v, t), s += v;
return aas[l] = max(aas[l], s - qa[l] + qa[l - 1] - df[l - 1] - dg[r + 1]), void();
}
Cdq(l, mid, lson), Cdq(mid + 1, r, rson);
tp[l - 1] = tp[r + 1] = 0;
for(int nl = mid; nl >= l; --nl){
for(auto [nr, v] : plb[nl]) if(nr <= r) nxt.Add(max(nr, mid + 1), r, v, mid + 1, r, rson);
tp[nl] = nxt.nd[rson] + qa[nl - 1] - df[nl - 1];
}
for(int nl = l; nl <= mid; ++nl) aas[nl] = max(aas[nl], tp[nl] = max(tp[nl], tp[nl - 1]));
for(int nr = mid + 1; nr <= r; ++nr){
for(auto [nl, v] : prb[nr]) if(l <= nl) pre.Add(l, min(mid, nl), -v, l, mid, lson);
tp[nr] = -qa[nr] - pre.nd[lson] - dg[nr + 1];
}
for(int nr = r; nr > mid; --nr) aas[nr] = max(aas[nr], tp[nr] = max(tp[nr], tp[nr + 1]));
pre.Upd(t), nxt.Upd(t);
}
#undef lson
#undef rson
#undef mid
void Dp(){
seg.Add(1, n, Inf);
for(int r = 1; r <= n; ++r){
seg.Add(r, r, -Inf + df[r - 1]), seg.Add(1, r, _a[r]);
for(auto [l, v] : pra[r]) seg.Add(1, l, -v);
df[r] = min(df[r - 1], seg.Get());
}
seg.Clr(), seg.Add(1, n, Inf);
for(int l = n; l; --l){
seg.Add(l, l, -Inf + dg[l + 1]), seg.Add(l, n, _a[l]);
for(auto [r, v] : pla[l]) seg.Add(r, n, -v);
dg[l] = min(dg[l + 1], seg.Get());
}
}
void Solve(){
cin >> n >> m;
llt sb = 0;
for(int i = 1; i <= n; ++i) cin >> _a[i], qa[i] = qa[i - 1] + _a[i];
for(int i = 1, l, r, b, t; i <= m; ++i){
cin >> l >> r >> b >> t;
if(!t) pla[l].emplace_back(r, b), pra[r].emplace_back(l, b);
plb[l].emplace_back(r, b), prb[r].emplace_back(l, b), sb += b;
}
Dp(), Cdq();
for(int i = 1; i <= n; ++i) cout << sb - max(aas[i], -df[i] - dg[i + 1]) << ' ';
cout << endl;
}
void Clear(){
for(int i = 1; i <= n; ++i) aas[i] = 0, pla[i].clear(), pra[i].clear(), plb[i].clear(), prb[i].clear();
memset(df, 0, sizeof df), memset(dg, 0, sizeof dg);
pre.Clr(), nxt.Clr(), seg.Clr();
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int tid, t;
cin >> tid >> t;
while(t--) Solve(), Clear();
}
P





本文來自博客園,作者:xrlong,轉(zhuǎn)載請注明原文鏈接:http://www.rzrgm.cn/xrlong/p/19110909
版權(quán)聲明:本作品采用 「署名-非商業(yè)性使用-相同方式共享 4.0 國際」許可協(xié)議(CC BY-NC-SA 4.0) 進行許可。

浙公網(wǎng)安備 33010602011771號