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