简单的线段树区间修改区间查询,但是因为数据范围过大,所以采用动态开点的方法(注意一下空间问题)。
也可以直接对询问区间的端点离散化然后建树,这种方法时间复杂度和空间复杂度都比较优秀。
给出动态开点的代码:
/*
* Author: heyuhhh
* Created Time: 2019/11/12 19:33:21
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '
'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 4e5 + 5;
int n, q;
int tot;
int rt[1];
int lc[N * 40], rc[N * 40], sum[N * 40], lz[N * 40];
void push_up(int o) {
sum[o] = sum[lc[o]] + sum[rc[o]];
}
void push_down(int o, int l, int r) {
if(lz[o] != -1) {
if(!lc[o]) lc[o] = ++tot;
if(!rc[o]) rc[o] = ++tot;
int mid = (l + r) >> 1;
sum[lc[o]] = (mid - l + 1) * lz[o];
lz[lc[o]] = lz[o];
sum[rc[o]] = (r - mid) * lz[o];
lz[rc[o]] = lz[o];
lz[o] = -1;
}
}
void upd(int &o, int l, int r, int L, int R, int v) {
if(!o) o = ++tot;
if(L <= l && r <= R) {
if(v == 0) sum[o] = lz[o] = 0;
else sum[o] = r - l + 1, lz[o] = 1;
return;
}
push_down(o, l, r);
int mid = (l + r) >> 1;
if(L <= mid) upd(lc[o], l, mid, L, R, v);
if(R > mid) upd(rc[o], mid + 1, r, L, R, v);
push_up(o);
}
void run(){
memset(lz, -1, sizeof(lz));
while(q--) {
int l, r, k; cin >> l >> r >> k;
if(k == 1) upd(rt[0], 1, n, l, r, 1);
else upd(rt[0], 1, n, l, r, 0);
int ans = n - sum[rt[0]];
cout << ans << '
';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> q) run();
return 0;
}