区间修改
小红的区间修改(二)
区间差分与合并,珂朵树
版本一
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct query{
int left, right;
ll c;
bool operator <(const query& other) const {
return left < other.left;
}
};
void solve() {
int q; cin >> q;
map<ll, int> col;
set<query> val;
int INF = 1e6;
val.insert({1, INF, 0}); col[0] = 1e6;
int ans = 1;
while(q --) {
int l, r, x; cin >> l >> r >> x;
auto it = val.lower_bound({l, r, x});
if(it == val.end() || (it!=val.begin() && prev(it)->left <= l && prev(it)->right >= r)) {
it = prev(it);
if(it->c != x) {
int L = it->left, R = it->right;
ll C = it->c;
val.erase(it);
col[it->c] -= r - l + 1;
if(col[x] == 0) ans ++;
col[x] += r - l + 1;
if(L <= l-1) val.insert({L, l-1, C});
if(r + 1 <= R) val.insert({r+1, R, C});
val.insert({l, r, x});
}
cout << ans << "\n";
continue;
}
if(it->left > l) {
auto pit = prev(it);
int PL = pit->left, PR = pit->right;
ll PC = pit->c;
val.erase(pit);
if(PC == x) {
l = PL;
col[x] -= PR - PL + 1;
if(col[x] == 0) ans --;
} else {
col[PC] -= PR - l + 1;
if(PL <= l - 1) val.insert({PL, l - 1, PC});
}
}
while(it != val.end() && it->right <= r) {
auto w = it;
it = next(it);
col[w->c] -= w->right - w->left + 1;
if(col[w->c] == 0) ans --;
val.erase(w);
}
if(it->left <= r) {
if(it->c == x) {
r = it->right;
col[x] -= it->right - it->left + 1;
if(col[x] == 0) ans --;
val.erase(it);
} else {
int L = it->left, R = it->right;
ll C = it->c;
col[C] -= r - L + 1;
val.erase(it);
if (r + 1 <= R) val.insert({r + 1, R, C});
}
}
if(col[x] == 0) ans ++;
col[x] += r - l + 1;
val.insert({l, r, x});
cout << ans << "\n";
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
solve();
return 0;
}
版本二
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct query{
int left, right;
ll c;
bool operator <(const query& other) const {
if(left != other.left) return left < other.left;
else if(right != other.right) return right < other.right;
return c < other.c;
}
};
void solve() {
int q; cin >> q;
map<ll, int> col;
set<query> val;
int INF = 1e6;
val.insert({1, INF, 0}); col[0] = 1e6;
int ans = 1;
while(q --) {
int l, r, x; cin >> l >> r >> x;
auto it = val.lower_bound({l, r, x});
if(it == val.end() || (it!=val.begin() && prev(it)->left <= l && prev(it)->right >= r)) {
it = prev(it);
if(it->c != x) {
col[it->c] -= r - l + 1;
if(col[it->c] == 0) ans --;
if(col[x] == 0) ans ++;
col[x] += r - l + 1;
if(it->left <= l-1) {query pr = {it->left, l - 1, it->c}; val.insert(pr);}
if(r + 1 <= it->right) {query su = {r + 1, it->right, it->c};val.insert(su);}
val.insert({l, r, x});
val.erase(it);
}
cout << ans << "\n";
continue;
}
if(it->left > l) {
auto pit = prev(it);
if(pit->c == x) {
l = pit->left;
col[x] -= pit->right - pit->left + 1;
} else {
col[pit->c] -= pit->right - l + 1;
if(pit->left < l) val.insert({pit->left, l - 1, pit->c});
}
if(col[pit->c] == 0) ans --;
val.erase(pit);
}
while(true) {
if(it->right > r) break;
auto w = it; it = next(it);
col[w->c] -= w->right - w->left + 1;
if(col[w->c] == 0) ans --;
val.erase(w);
}
if(it->left <= r) {
if(it->c == x) {
r = it->right;
col[x] -= it->right - it->left + 1;
} else {
col[it->c] -= r - it->left + 1;
if(r < it->right) val.insert({r + 1, it->right, it->c});
}
if(col[it->c] == 0) ans --;
val.erase(it);
}
if(col[x] == 0) ans ++;
col[x] += r - l + 1;
val.insert({l, r, x});
cout << ans << "\n";
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
solve();
return 0;
}
版本三——珂朵树
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 1e9;
struct Node {
int l, r;
mutable ll val;// mutable 允许在 set 中修改 val
Node(int _l, int _r = -1, ll _val = 0) : l(_l), r(_r), val(_val) {}
bool operator<(const Node& o) const {
return l < o.l;
}
};
set<Node> tree;
map<ll, int> cnt;
int ans = 1;
// 将 pos 所在段分裂成 [l, pos-1] 和 [pos, r],返回 pos 所在段的迭代器
auto split(int pos) {
auto it = tree.lower_bound(Node(pos));
if(it != tree.end() && it->l == pos) return it;
--it; // it 现在是包含 pos 的段
int L = it->l, R = it->r;
ll V = it->val;
tree.erase(it);
if(L <= pos - 1) tree.insert(Node(L, pos - 1, V));
return tree.insert(Node(pos, R, V)).first;
}
// 区间 [l, r] 赋值为 val
void assign(int l, int r, ll val) {
auto itr = split(r + 1); // 先切右端点,防止迭代器失效
auto itl = split(l); // 再切左端点
// 删除 [itl, itr) 的所有段,并更新 cnt
for(auto it = itl; it != itr; ++it) {
int len = it->r - it->l + 1;
cnt[it->val] -= len;
if(cnt[it->val] == 0) ans--;
}
tree.erase(itl, itr);
tree.insert(Node(l, r, val));
cnt[val] += r - l + 1;
if(cnt[val] == r - l + 1) ans ++;// 等价于原来 cnt[val]==0
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int q; cin >> q;
tree.insert(Node(1, INF, 0));
cnt[0] = INF;
while(q --) {
int l, r, x; cin >> l >> r >> x;
assign(l, r, x);
cout << ans << '\n';
}
return 0;
}

浙公网安备 33010602011771号