P3261 [JLOI2015]城池攻占 [贪心,左偏树]
板子吧,左偏树合并是 1log 的,按照深度合并,而且可以打 tag,pushdown。
// by Isaunoya
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct io {
char buf[1 << 27 | 3], *s;
int f;
io() { f = 0, buf[fread(s = buf, 1, 1 << 27, stdin)] = '\n'; }
io& operator >> (int&x) {
for(x = f = 0; !isdigit(*s); ++s) f |= *s == '-';
while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
return x = f ? -x : x, *this;
}
};
int n, m;
const int maxn = 3e5 + 53;
vector <int> g[maxn];
int qwq[maxn], val[maxn], mul[maxn], add[maxn];
int h[maxn];
int v[maxn], c[maxn];
int rt[maxn], ls[maxn], rs[maxn];
void down(int p, int c, int vv) {
if(! p) return;
v[p] *= c, v[p] += vv;
mul[p] *= c, add[p] *= c; add[p] += vv;
}
void down(int p) {
down(ls[p], mul[p], add[p]);
down(rs[p], mul[p], add[p]);
mul[p] = 1, add[p] = 0;
}
int dis[maxn];
int merge(int x, int y) {
if(!x || !y) return x + y;
down(x), down(y);
if(v[x] > v[y]) swap(x, y);
rs[x] = merge(rs[x], y);
if(dis[ls[x]] < dis[rs[x]]) swap(ls[x], rs[x]);
dis[x] = dis[rs[x]] + 1;
return x;
}
int ans1[maxn], ans2[maxn];
int dep[maxn];
void dfs(int u, int f) {
dep[u] = dep[f] + 1;
for(int v: g[u]) dfs(v, u), rt[u] = merge(rt[u], rt[v]);
while(rt[u] && v[rt[u]] < h[u]) {
down(rt[u]); ++ ans1[u];
ans2[rt[u]] = dep[c[rt[u]]] - dep[u];
rt[u] = merge(ls[rt[u]], rs[rt[u]]);
}
if(qwq[u]) down(rt[u], val[u], 0);
else down(rt[u], 1, val[u]);
}
signed main() {
#ifdef LOCAL
freopen("testdata.in", "r", stdin);
#endif
io in;
in >> n >> m;
for(int i = 1 ; i <= n ; i ++) in >> h[i];
for(int i = 2 ; i <= n ; i ++) {
int f;
in >> f >> qwq[i] >> val[i];
g[f].push_back(i);
}
for(int i = 1 ; i <= m ; i ++) {
in >> v[i] >> c[i];
mul[i] = 1;
rt[c[i]] = merge(rt[c[i]], i);
}
dfs(1, 0);
while(rt[1]) {
down(rt[1]);
ans2[rt[1]] = dep[c[rt[1]]];
rt[1] = merge(ls[rt[1]], rs[rt[1]]);
}
for(int i = 1 ; i <= n ; i ++)
cout << ans1[i] << '\n';
for(int i = 1 ; i <= m ; i ++)
cout << ans2[i] << '\n';
return 0;
}