sequence
我們會發現,我們每次刪的一定是長度最短的那個,所以我們可以最開始按照長的排一下序,然後用線段樹維護每一個區間中還有幾個數,每次加上答案後在兩個端點打上標記即可
#include <bits/stdc++.h>
#define _1 (__int128)1
using namespace std;
using ll = long long;
void FileIO (const string s) {
freopen(string(s + ".in").c_str(), "r", stdin);
freopen(string(s + ".out").c_str(), "w", stdout);
}
const int N = 2e5 + 10;
inline int lowbit (int x) {
return x & -x;
}
struct Num {
int l, r;
} a[N];
int n, tr[N];
ll ans;
void modify (int x, int lv) {
while (x) tr[x] += lv, x -= lowbit(x);
}
int Query (int x) {
int ret = 0;
while (x <= 2 * n) ret += tr[x], x += lowbit(x);
return ret;
}
signed main () {
ios::sync_with_stdio(0), cin.tie(0);
FileIO("sequence");
cin >> n;
for (int i = 1, x; i <= 2 * n; i++)
cin >> x, a[x] = (!a[x].l ? Num{i, 0} : Num{a[x].l, i});
sort(a + 1, a + n + 1, [](const Num &i, const Num &j){return i.l < j.l;});
for (int i = 1; i <= n; i++)
ans += a[i].r - a[i].l - Query(a[i].l) - Query(a[i].r), modify(a[i].r, 1);
cout << ans;
return 0;
}
slime
令 \(dp_{u, 0/1}\) 表示沒有刪除史萊姆操作時能得到的體積,刪除一個史萊姆能減少的最大體積 。
那麼我們可以顯然得到兩個轉移
\[dp_{u, 0} = dp_{u, 0} + \sum_{v \in son_u} \max(0, dp_{v, 0} - w)\\
dp_{u, 1} = \max(dp_{u, 1}, \max_{v \in son_u}(\max(0, dp_{v, 0}) - \max(0, dp_{v,0} - dp_{v, 1} - w)))
\]
那麼我們可以再設 \(ans_{u, 0/1}\) 表示將 \(u\) 作為根時不用刪除可以得到史萊姆的體積,刪除一個史萊姆可以減少的最大體積。
從 \(u\) 轉移至 \(v\) 時,令 \(cur\) 表示 \(u\) 對 \(ans_{v, 0}\) 的貢獻,\(cur = ans_{0, u} - \max(0, dp_{0, v} - w) - w\),請看圖,圖中解釋了為什麼是這個貢獻
所以我們就可以輕鬆得出式子
\[ans_{v, 0} = dp_{v, 0} + \max(0, k)\\
ans_{v, 1} = \max(dp_{v, 1}, \max(0, k) - \max(0, k - ans_{u, 1}))
\]
查詢時答案就是 \(ans_{0, c_i} - ans_{1, c_i} \times num_i\)
#include <bits/stdc++.h>
using namespace std;
using Pii = pair<long long, long long>;
#define int long long
const int N = 2e5 + 5;
int n, k, q, a[N];
int dp[N][2], ans[N][2];
vector<Pii> g[N];
void dfs(int u, int f) {
dp[u][0] = dp[u][1] = a[u];
for (auto [v, w] : g[u]) {
if (v == f) {
continue;
}
dfs(v, u);
int cur = dp[v][0] - w;
dp[u][0] += max(0ll, cur);
dp[u][1] = max(dp[u][1], max(0ll, cur) - max(0ll, cur - dp[v][1]));
}
}
void DFS(int u, int f) {
ans[u][0] += dp[u][0];
ans[u][1] = max(ans[u][1], dp[u][1]);
for (auto [v, w] : g[u]) {
if (v == f) {
continue;
}
int cur = ans[u][0] - max(0ll, dp[v][0] - w) - w;
ans[v][0] = max(0ll, cur);
ans[v][1] = max(0ll, cur) - max(0ll, cur - ans[u][1]);
DFS(v, u);
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
freopen("slime.in", "r", stdin);
freopen("slime.out", "w", stdout);
cin >> n >> k >> q;
for (int i = 1, u, v, w; i < n; i++) {
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
}
for (int i = 1, p, x; i <= k; i++) {
cin >> p >> x;
a[p] = x;
}
dfs(1, 0);
DFS(1, 0);
while (q--) {
int u, x;
cin >> u >> x;
cout << ans[u][0] - x * ans[u][1] << "\n";
}
return 0;
}