Skip to content

Commit ca0b3a8

Browse files
Add files via upload
1 parent a9cb4ef commit ca0b3a8

File tree

1 file changed

+272
-0
lines changed

1 file changed

+272
-0
lines changed
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#pragma GCC optimize("Ofast")
2+
#pragma GCC optimize("unroll-loops")
3+
#include <bits/stdc++.h>
4+
using namespace std;
5+
6+
typedef long long ll;
7+
typedef vector<int> vi;
8+
#define fast_cin() \
9+
ios_base::sync_with_stdio(false); \
10+
cin.tie(NULL); \
11+
cout.tie(NULL);
12+
13+
struct node {
14+
int s, e;
15+
ll mn, mx, sum, add_val, set_val;
16+
bool lset;
17+
node *l, *r;
18+
node(int _s, int _e, int A[] = NULL)
19+
: s(_s), e(_e), mn(0), mx(0), sum(0), add_val(0), set_val(0), lset(0), l(NULL), r(NULL) {
20+
if (A == NULL) return;
21+
if (s == e)
22+
mn = mx = sum = A[s];
23+
else {
24+
l = new node(s, (s + e) >> 1, A), r = new node((s + e + 2) >> 1, e, A);
25+
combine();
26+
}
27+
}
28+
void create_children() {
29+
if (s == e) return;
30+
if (l != NULL) return;
31+
int m = (s + e) >> 1;
32+
l = new node(s, m);
33+
r = new node(m + 1, e);
34+
}
35+
void self_set(ll v) {
36+
lset = 1;
37+
mn = mx = set_val = v;
38+
sum = v * (e - s + 1);
39+
add_val = 0;
40+
}
41+
void self_add(ll v) {
42+
if (lset) {
43+
self_set(v + set_val);
44+
return;
45+
}
46+
mn += v, mx += v, add_val += v;
47+
sum += v * (e - s + 1);
48+
}
49+
void lazy_propagate() {
50+
if (s == e) return;
51+
if (lset) {
52+
l->self_set(set_val), r->self_set(set_val);
53+
lset = set_val = 0;
54+
}
55+
if (add_val != 0) {
56+
l->self_add(add_val), r->self_add(add_val);
57+
add_val = 0;
58+
}
59+
}
60+
void combine() {
61+
if (l == NULL) return;
62+
sum = l->sum + r->sum;
63+
mn = min(l->mn, r->mn);
64+
mx = max(l->mx, r->mx);
65+
}
66+
#define UPDATE(name) \
67+
void name(int x, int y, ll v) { \
68+
if (s == x && e == y) { \
69+
self_##name(v); \
70+
return; \
71+
} \
72+
int m = (s + e) >> 1; \
73+
create_children(); \
74+
lazy_propagate(); \
75+
if (x <= m) l->name(x, min(y, m), v); \
76+
if (y > m) r->name(max(x, m + 1), y, v); \
77+
combine(); \
78+
}
79+
UPDATE(add) // generates add
80+
UPDATE(set) // generates set
81+
#define QUERY(name, fn, var, lazyfn) \
82+
ll range_##name(int x, int y) { \
83+
if (s == x && e == y) return var; \
84+
if (l == NULL || lset) return lazyfn(var); \
85+
int m = (s + e) >> 1; \
86+
lazy_propagate(); \
87+
if (y <= m) return l->range_##name(x, y); \
88+
if (x > m) return r->range_##name(x, y); \
89+
return fn(l->range_##name(x, m), r->range_##name(m + 1, y)); \
90+
}
91+
#define SAME(var) (var)
92+
#define PART(var) ((var) / (e - s + 1) * (y - x + 1))
93+
#define SUM(a, b) ((a) + (b))
94+
QUERY(min, min, mn, SAME) // generates range_min
95+
QUERY(max, max, mx, SAME) // generates range_max
96+
QUERY(sum, SUM, sum, PART) // generates range_sum
97+
~node() {
98+
if (l != NULL) delete l;
99+
if (r != NULL) delete r;
100+
}
101+
102+
ll first_idx_greater_than(int x, int y, ll v) {
103+
if (mx <= v) return -1;
104+
if (s == e) return s;
105+
if (l == NULL || lset) return max(x, s); // if all the same, return the left most index
106+
107+
int m = (s + e) >> 1;
108+
lazy_propagate();
109+
if (y <= m) return l->first_idx_greater_than(x, y, v);
110+
if (x > m) return r->first_idx_greater_than(x, y, v);
111+
112+
int leftidx = l->first_idx_greater_than(x, m, v);
113+
if (leftidx != -1) return leftidx; // not found in left subtree
114+
return r->first_idx_greater_than(m + 1, y, v);
115+
}
116+
117+
ll first_idx_smaller_than(int x, int y, ll v) {
118+
if (mn >= v) return -1;
119+
if (s == e) return s;
120+
if (l == NULL || lset) return max(x, s); // if all the same, return the left most index
121+
122+
int m = (s + e) >> 1;
123+
lazy_propagate();
124+
if (y <= m) return l->first_idx_smaller_than(x, y, v);
125+
if (x > m) return r->first_idx_smaller_than(x, y, v);
126+
127+
int leftidx = l->first_idx_smaller_than(x, m, v);
128+
if (leftidx != -1) return leftidx; // not found in left subtree
129+
return r->first_idx_smaller_than(m + 1, y, v);
130+
}
131+
132+
ll last_idx_smaller_than(int x, int y, ll v) {
133+
if (mn >= v) return -1;
134+
if (s == e) return s;
135+
if (l == NULL || lset) return min(y, e); // if all the same, return the right most index
136+
137+
int m = (s + e) >> 1;
138+
lazy_propagate();
139+
if (y <= m) return l->last_idx_smaller_than(x, y, v);
140+
if (x > m) return r->last_idx_smaller_than(x, y, v);
141+
142+
int rightidx = r->last_idx_smaller_than(m + 1, y, v);
143+
if (rightidx != -1) return rightidx; // not found in right subtree
144+
return l->last_idx_smaller_than(x, m, v);
145+
}
146+
147+
ll last_idx_greater_than(int x, int y, ll v) {
148+
if (mx <= v) return -1;
149+
if (s == e) return s;
150+
if (l == NULL || lset) return min(y, e); // if all the same, return the right most index
151+
152+
int m = (s + e) >> 1;
153+
lazy_propagate();
154+
if (y <= m) return l->last_idx_greater_than(x, y, v);
155+
if (x > m) return r->last_idx_greater_than(x, y, v);
156+
157+
int rightidx = r->last_idx_greater_than(m + 1, y, v);
158+
if (rightidx != -1) return rightidx; // not found in right subtree
159+
return l->last_idx_greater_than(x, m, v);
160+
}
161+
};
162+
163+
int n, m;
164+
vector<int> low; // low(r) is the lowest i such that statements[i..r] are satisfiable
165+
vector<tuple<int, int, int>> arr;
166+
vector<tuple<int, int, int>> b_stmts; // {r, l, idx}
167+
vector<int> b_stmt_idx; // b_stmt_idx[i] is the position of stmt i in b_stmts
168+
void solve() {
169+
cin >> n >> m;
170+
arr.resize(m);
171+
b_stmt_idx.assign(m, -1);
172+
b_stmts.clear();
173+
b_stmts.reserve(m);
174+
for (int i = 0; i < m; i++) {
175+
int a, b, c;
176+
cin >> a >> b >> c;
177+
arr[i] = {a, b, c};
178+
if (a == 1) {
179+
b_stmts.emplace_back(c, b, i);
180+
}
181+
}
182+
183+
sort(b_stmts.begin(), b_stmts.end());
184+
for (int i = 0; i < (int)b_stmts.size(); i++) {
185+
auto [r, l, idx] = b_stmts[i];
186+
b_stmt_idx[idx] = i;
187+
}
188+
189+
unique_ptr<node> blx(new node(0, m));
190+
blx->set(0, m, -1); // all not activated initialy
191+
192+
int left = 0;
193+
unique_ptr<node> root(new node(0, n + 1));
194+
low.assign(m, -1);
195+
// sliding window
196+
for (int i = 0; i < m; i++) {
197+
auto [op, l, r] = arr[i];
198+
if (op == 0) {
199+
root->add(l, r, 1);
200+
while (true) {
201+
int cl = root->last_idx_smaller_than(0, l, 1) + 1;
202+
int cr = root->first_idx_smaller_than(r, n + 1, 1) - 1;
203+
204+
assert(root->range_min(cl, cr) > 0);
205+
assert(root->range_min(cl - 1, l) == 0);
206+
assert(root->range_min(r, cr + 1) == 0);
207+
208+
// check if okay
209+
int br_idx =
210+
upper_bound(b_stmts.begin(), b_stmts.end(), make_tuple(cr + 1, -1, -1)) -
211+
b_stmts.begin();
212+
if (br_idx == 0) {
213+
break;
214+
}
215+
br_idx--;
216+
217+
int bl = blx->range_max(0, br_idx);
218+
219+
if (bl >= cl) { // completely covered, must remove from the left
220+
auto [op2, l2, r2] = arr[left];
221+
if (op2 == 0) {
222+
root->add(l2, r2, -1);
223+
} else {
224+
blx->set(b_stmt_idx[left], b_stmt_idx[left], -1);
225+
}
226+
left++;
227+
} else {
228+
break;
229+
}
230+
}
231+
232+
} else {
233+
bool check = true;
234+
while (true) {
235+
if (check && root->range_min(l, r) == 0) break; // avoids rechecks
236+
assert(left < i);
237+
auto [op2, l2, r2] = arr[left];
238+
if (op2 == 0) {
239+
root->add(l2, r2, -1);
240+
check = true;
241+
} else {
242+
blx->set(b_stmt_idx[left], b_stmt_idx[left], -1);
243+
check = false;
244+
}
245+
left++;
246+
}
247+
blx->set(b_stmt_idx[i], b_stmt_idx[i], l);
248+
}
249+
low[i] = left;
250+
}
251+
252+
int q;
253+
cin >> q;
254+
for (int i = 0; i < q; i++) {
255+
int l, r;
256+
cin >> l >> r;
257+
l--, r--;
258+
if (low[r] <= l) {
259+
cout << "YES\n";
260+
} else {
261+
cout << "NO\n";
262+
}
263+
}
264+
}
265+
266+
int main() {
267+
fast_cin();
268+
int tc;
269+
cin >> tc;
270+
while (tc--) solve();
271+
return 0;
272+
}

0 commit comments

Comments
 (0)