「USACO 2019.12 Platinum」Bessie's Snow Cow

#3227. 「USACO 2019.12 Platinum」Bessie’s Snow Cow

Summarize

给定$n$个节点的一棵有根树,$q$次操作,每次操作可以令一个节点的子树的所有节点增加一个颜色$i$,或查询一个节点的颜色数

$1 \le n,q \le 10^5$

感谢@oy的贡献

Solution

考虑维护 $C$ 个数据结构,存储每种颜色所对应的 $\text{dfs}$ 序的区间。根据 势能分析 可证明复杂度。剩余部分用线段树模拟即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN = 1e5 + 5;

vector<int> G[MAXN];
set<pair<int, int> > S[MAXN];

struct Segment_Tree {
#define lson(u) node[u].l
#define rson(u) node[u].r
#define val(u) node[u].val
#define tag(u) node[u].tag
struct Node {
int l, r;
ll val, tag;
}node[MAXN << 1];
int R, cnt;
void pushup(int u) {
val(u) = val(lson(u)) + val(rson(u));
}
void pushdown(int u, int l, int r) {
if (tag(u) == 0) return;
int mid = (l + r) >> 1;
int llen = mid - l + 1, rlen = r - mid;
val(lson(u)) += 1ll * llen * tag(u),
val(rson(u)) += 1ll * rlen * tag(u);
tag(lson(u)) += tag(u),
tag(rson(u)) += tag(u);
tag(u) = 0;
}
void build(int& u, int l, int r) {
u = ++cnt;
if (l == r) return;
int mid = (l + r) >> 1;
build(lson(u), l, mid), build(rson(u), mid + 1, r);
pushup(u);
}
void modify_range(int u, int l, int r, int ql, int qr, ll val) {
if (ql <= l && r <= qr) {
val(u) += 1ll * (r - l + 1) * val;
tag(u) += val;
return;
}
pushdown(u, l, r);
int mid = (l + r) >> 1;
if (ql <= mid)
modify_range(lson(u), l, mid, ql, qr, val);
if (mid < qr)
modify_range(rson(u), mid + 1, r, ql, qr, val);
pushup(u);
}
ll query_range(int u, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr)
return val(u);
pushdown(u, l, r);
int mid = (l + r) >> 1;
ll ret = 0;
if (ql <= mid)
ret += query_range(lson(u), l, mid, ql, qr);
if (mid < qr)
ret += query_range(rson(u), mid + 1, r, ql, qr);
return ret;
}
}T;

int n, q;
int dfn[MAXN], size[MAXN], dfn_idx;

void dfs(int u, int fa) {
dfn[u] = ++dfn_idx;
size[u] = 1;
for (auto v : G[u]) {
if (v == fa) continue;
dfs(v, u);
size[u] += size[v];
}
}

int main() {
scanf("%d%d", &n, &q);
for (int i = 1; i < n; ++i) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v), G[v].push_back(u);
}
dfs(1, 0);
T.build(T.R, 1, n);
while (q--) {
int op, x, c;
scanf("%d%d", &op, &x);
int l = dfn[x], r = dfn[x] + size[x] - 1;
if (op == 2) {
printf("%lld\n", T.query_range(T.R, 1, n, l, r));
} else {
scanf("%d", &c);
set<pair<int, int> >::iterator it = S[c].lower_bound(make_pair(l, r));
int nl = l, nr = r;
if (it != S[c].begin()) {
it--;
if (it->second >= l) {
nl = it->first;
nr = max(r, it->second);
T.modify_range(T.R, 1, n, it->first, it->second, -1);
S[c].erase(it++);
} else it++;
}
while (it != S[c].end() && it->first <= r + 1) {
nr = max(r, it->second);
T.modify_range(T.R, 1, n, it->first, it->second, -1);
S[c].erase(it++);
}
T.modify_range(T.R, 1, n, nl, nr, 1);
S[c].insert(make_pair(nl, nr));

}
}
return 0;
}

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×