-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathE. Party Company.cpp
172 lines (150 loc) · 3.62 KB
/
E. Party Company.cpp
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
> put the party up until the maximum allowed boss
> find such boss with binary lifting in a greddy way
> for each node store the party info [ [l1, r1], ... [ln, rn] ]
> keep a segment tree where st[i] = the amount of parties that
a age i is allowed
*/
#include <bits/stdc++.h>
using namespace std;
using ll = int;
struct Lnode {
ll v;
bool assign;
Lnode() : v(), assign() {} // Neutral element
Lnode(ll _v, bool a = 0) : v(_v), assign(a){};
};
using Qnode = ll;
using Unode = Lnode;
struct LSegTree {
int n, ql, qr;
vector<Qnode> st;
vector<Lnode> lz;
/*-8<--------------------------------------------------------------->8-*/
Qnode merge(Qnode lv, Qnode rv, int nl, int nr) {
return lv + rv;
}
void prop(int i, int l, int r) {
if (lz[i].assign) {
st[i] = lz[i].v * (r - l + 1);
if (l != r) lz[tol(i)] = lz[tor(i)] = lz[i];
} else {
st[i] += lz[i].v * (r - l + 1);
if (l != r)
lz[tol(i)].v += lz[i].v, lz[tor(i)].v += lz[i].v;
}
lz[i] = Lnode();
}
void applyV(int i, Unode v) {
if (v.assign) {
lz[i] = v;
} else {
lz[i].v += v.v;
}
}
/*-8<--------------------------------------------------------------->8-*/
LSegTree() {}
LSegTree(int _n) : n(_n), st(_n << 2), lz(_n << 2) {}
bool disjoint(int l, int r) { return qr < l or r < ql; }
bool contains(int l, int r) {
return ql <= l and r <= qr;
}
int tol(int i) { return i << 1; }
int tor(int i) { return i << 1 | 1; }
void build(vector<Qnode> &v) { build(v, 1, 0, n - 1); }
void build(vector<Qnode> &v, int i, int l, int r) {
if (l == r) {
st[i] = v[l];
return;
}
int m = midpoint(l, r);
build(v, tol(i), l, m);
build(v, tor(i), m + 1, r);
st[i] = merge(st[tol(i)], st[tor(i)], l, r);
}
void upd(int l, int r, Unode v) {
ql = l, qr = r;
upd(1, 0, n - 1, v);
}
void upd(int i, int l, int r, Unode v) {
prop(i, l, r);
if (disjoint(l, r)) return;
if (contains(l, r)) {
applyV(i, v);
prop(i, l, r);
return;
}
int m = midpoint(l, r);
upd(tol(i), l, m, v);
upd(tor(i), m + 1, r, v);
st[i] = merge(st[tol(i)], st[tor(i)], l, r);
}
Qnode qry(int l, int r) {
ql = l, qr = r;
return qry(1, 0, n - 1);
}
Qnode qry(int i, int l, int r) {
prop(i, l, r);
if (disjoint(l, r)) return Qnode();
if (contains(l, r)) return st[i];
int m = midpoint(l, r);
return merge(qry(tol(i), l, m), qry(tor(i), m + 1, r),
l, r);
}
};
const int MAX(1'00'000);
int N, M;
int AGES[MAX];
vector<int> SUBORDINATES[MAX];
const int MAXLOG = 25;
int jump[MAX][MAXLOG];
void calc_binary_lifting() {
for (int i = 1; i < MAXLOG; i++) {
for (int j = 0; j < N; j++) {
jump[j][i] = jump[jump[j][i-1]][i-1];
}
}
}
int find_owner(int u, int maxr) {
for (int i = MAXLOG-1; i >= 0; i--) {
if (AGES[jump[u][i]] <= maxr)
u = jump[u][i];
}
return u;
}
vector<pair<int,int>> parties[MAX];
int ans[MAX];
LSegTree st(MAX+1);
void dfs(int u) {
for (auto [l, r] : parties[u])
st.upd(l, r, 1);
ans[u] = st.qry(AGES[u], AGES[u]);
for (auto v : SUBORDINATES[u]) {
dfs(v);
}
for (auto [l, r] : parties[u])
st.upd(l, r, -1);
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N >> M;
for (int i = 0; i < N; i++) {
cin >> AGES[i];
cin >> jump[i][0];
jump[i][0]--;
if (i)
SUBORDINATES[jump[i][0]].emplace_back(i);
}
calc_binary_lifting();
for (int i = 0; i < M; i++) {
int o, l, r;
cin >> o >> l >> r;
o = find_owner(o-1, r);
parties[o].emplace_back(l, r);
}
dfs(0);
for (int i = 0; i < N; i++) {
cout << ans[i] << " \n"[i == N-1];
}
}