题目大意:有$n$个点,原来都是$1$,$m$次区间修改,将$[l,r]$中所有元素改为一个值,问每次操作后$n$个点的和。$nleqslant10^9,mleqslant3 imes10^5$
题解:动态开点线段树,但是因为刚学习$ODT$,就拿这道题练手,直接相同元素直接修改,在修改的同时更新答案。
卡点:无
C++ Code:
#include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <iostream> int n, q, ans; namespace ODT { struct node { int l, r; mutable int v; inline bool operator < (const node &rhs) const { return l < rhs.l; } } ; std::set<node> s; typedef std::set<node>::iterator SIT; SIT split(int pos) { SIT it = s.lower_bound((node) { pos, 0, 0 }); if (it != s.end() && it -> l == pos) return it; --it; const int l = it -> l, r = it -> r, v = it -> v; s.erase(it), s.insert((node) { l, pos - 1, v }); return s.insert((node) { pos, r, v}).first; } void assign(int l, int r, int v) { SIT R = split(r + 1), L = split(l); for (SIT it = L; it != R; ++it) ans -= it -> v * (it -> r - it -> l + 1); s.erase(L, R), s.insert((node) { l, r, v }); ans += v * (r - l + 1); } } int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> n >> q; ans = n; ODT::s.insert((ODT::node) { 1, n, 1 }); while (q --> 0) { static int l, r, x; std::cin >> l >> r >> x; --x; ODT::assign(l, r, x); std::cout << ans << ' '; } return 0; }