CF1455G
Statement
題目寫的很清楚了,看題目的翻譯吧。
Solution
考慮 if 指令形成了一個嵌套關(guān)系,是一個層層包含的過程。
于是可以將每個 if 指令與被他包含的指令之間連邊,然后在開頭加上一個指令 if 0,這樣,我們就將題目所示的關(guān)系建成了一顆樹。
我們現(xiàn)在希望的是,刪除某些 set 操作,然后使得最終遍歷這個樹并執(zhí)行對應(yīng)的操作后,任意時刻都不會使 \(x= s\)。
不難發(fā)現(xiàn),從任意一棵樹開始執(zhí)行操作,最終從這個樹中操作結(jié)束后,得到的值 \(x\),一定為子樹中的某個 set y v 的 \(v\)。
注意到最后得到某個數(shù) \(j\) 且中途不出現(xiàn) \(x = s\) 代表著操作的結(jié)束,根據(jù)這個在樹上做一個 dp,設(shè) \(dp_{i,j}\) 表示在 \(i\) 的子樹中,刪除若干操作后最后得到的 \(x = j\) 的最小代價。
每次假如在樹上碰到了葉子節(jié)點也就是 set y v 操作的時候,對于 \(j \neq y\) 的全部都要加上值 \(v\),對于 \(y\) 在特判一下 \(y \neq s\),如果 \(y\) 等于 \(s\) 的話,將其設(shè)為 \(\infty\),否則選擇 \(j \neq y\) 的最小的一個值 \(dp_{i,j}\) 然后更新 \(dp_{i,y}\) 即可。
假如碰到了一個非葉子節(jié)點也就是 if y 操作的時候,首先需要判斷一下是否能執(zhí)行 \(y\) 操作,如果能的話,首先遞歸處理兒子子樹內(nèi)的答案,之后對兒子 \(dp_{to,j}\) 全體加上 \(dp_{i,j}\) 表示執(zhí)行的前置代價,再將 \(dp_{i, y}\) 的值設(shè)為 \(dp_{to, y}\),因為此時會要考慮子節(jié)點的貢獻,之后對于其他的 \(j\),將 \(dp_{i,j}\) 與 \(dp_{to, j}\) 對應(yīng)取 \(\min\) 即可。
不難發(fā)現(xiàn)這個是一個整體 \(dp\) 的過程,于是可以考慮對每個點開一顆動態(tài)開點值域線段樹進行優(yōu)化,然后算子節(jié)點對父節(jié)點的貢獻的時候直接線段樹合并即可,復(fù)雜度 \(n \log n\)。
當(dāng)然,也可以考慮使用啟發(fā)式合并計算子節(jié)點對父節(jié)點的貢獻,因為中途遞歸子節(jié)點的時候需要給子節(jié)點全局加上某個值 \(val\),此時需要在合并中對連通塊維護懶惰標(biāo)記來存儲 \(val\),然后合并的時候如果是當(dāng)前節(jié)點大,那么兒子直接暴力加 \(val\),不用管了,如果是當(dāng)前兒子大,那么對于當(dāng)前節(jié)點中每個點先 \(-dp_{i,j}\),然后全局加上一個 \(dp_{i,j}\) 就好了,而其他查詢最小的值,額外再開一個 multiset 即可維護,復(fù)雜度 \(n\log^2 n\)。
代碼實現(xiàn)的是整體 \(dp\) 的代碼。
// 德麗莎你好可愛德麗莎你好可愛德麗莎你好可愛德麗莎你好可愛德麗莎你好可愛
// 德麗莎的可愛在于德麗莎很可愛,德麗莎為什么很可愛呢,這是因為德麗莎很可愛!
// 沒有力量的理想是戲言,沒有理想的力量是空虛
#include <bits/stdc++.h>
#define LL long long
#define int long long
using namespace std;
char ibuf[1 << 15], *p1, *p2;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, 1 << 15, stdin), p1==p2) ? EOF : *p1++)
inline int read() {
char ch = getchar(); int x = 0, f = 1;
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return x * f;
}
void print(LL x) {
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
template<class T> bool chkmin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool chkmax(T &a, T b) { return a < b ? (a = b, true) : false; }
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define repd(i, l, r) for (int i = (l); i >= (r); i--)
#define REP(i, l, r) for (int i = (l); i < (r); i++)
bool o1;
const int N = 2e5 + 5, lim = 2e5, inf = 2e17;
int n, S, num, nex[N], first[N], v[N];
int st[N], tp;
struct node { int id, x, y; } a[N];
vector <int> ver[N];
int rt[N * 19], lc[N * 19], rc[N * 19], s[N * 19], tot, tag[N * 19];
void pushup(int p) {
s[p] = min(s[lc[p]], s[rc[p]]);
}
void gettag(int p,int val) {
s[p] += val;
tag[p] += val;
}
void pushdown(int p) {
if (!tag[p]) return;
if (lc[p]) s[lc[p]] += tag[p], tag[lc[p]] += tag[p];
if (rc[p]) s[rc[p]] += tag[p], tag[rc[p]] += tag[p];
tag[p] = 0;
}
void change(int &p,int l,int r,int pos,int val) {
if (!p) p = ++tot;
if (l == r) { s[p] = val; return; }
pushdown(p);
int mid = (l + r) >> 1;
if (pos <= mid) change(lc[p], l, mid, pos, val);
else change(rc[p], mid + 1, r, pos, val);
pushup(p);
}
int ask(int p,int l,int r,int pos) {
if (!p) return inf;
if (l == r) return s[p];
pushdown(p);
int mid = (l + r) >> 1;
if (pos <= mid) return ask(lc[p], l, mid, pos);
else return ask(rc[p], mid + 1, r, pos);
}
int merge(int x,int y,int a,int b) {
if (!x || !y) return x + y;
int nowrt = ++tot;
if (a == b) {
s[nowrt] = min(s[x], s[y]);
return nowrt;
}
pushdown(x);
pushdown(y);
int mid = (a + b) >> 1;
lc[nowrt] = merge(lc[x], lc[y], a, mid);
rc[nowrt] = merge(rc[x], rc[y], mid + 1, b);
pushup(nowrt);
return nowrt;
}
int cnt = 0;
void dfs(int x) {
change(rt[x], 0, lim, a[x].x, 0);
for (auto to : ver[x]) {
if (a[to].id == 1) {
int now = s[rt[x]];
gettag(rt[x], a[to].y);
if (a[to].x != S) change(rt[x], 0, lim, a[to].x, now);
else change(rt[x], 0, lim, a[to].x, inf);
} else if (a[to].id == 2) {
int val = ask(rt[x], 0, lim, a[to].x);
if (val != inf) {
dfs(to);
gettag(rt[to], val);
change(rt[x], 0, lim, a[to].x, inf);
rt[x] = merge(rt[x], rt[to], 0, lim);
}
}
}
}
bool o2;
void solve() {
// cout << (&o2 - &o1) * 1.0 / 1024 / 1024 << "\n";
cin >> n >> S;
st[0] = n + 1;
rep (i, 1, n) {
string it ;
cin >> it;
if (it == "set") {
a[i].id = 1;
cin >> a[i].x >> a[i].y;
ver[st[tp]].push_back(i);
} else if (it == "if") {
a[i].id = 2;
cin >> a[i].x;
ver[st[tp]].push_back(i);
st[++tp] = i;
} else if (it == "end") {
tp--;
}
}
s[0] = inf;
dfs(n + 1);
cout << s[rt[n + 1]] << "\n";
}
signed main () {
#ifdef LOCAL_DEFINE
freopen("1.in", "r", stdin);
freopen("1.ans", "w", stdout);
#endif
ios :: sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1; while (T--) solve();
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}

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