题解 P2082 【区间覆盖(加强版)】

SuperJvRuo

2018-10-02 18:50:08

Solution

操作只有区间赋值,emmm... ## 用珂朵莉树啊!(第一反应真的是这个 [【暴力数据结构Warning】Chtholly Tree珂朵莉树](https://www.luogu.org/blog/ACdreamer/chtholly-tree) 把连续的区间存在```std::set```之中,区间覆盖的时候把这一段```split```出来,然后更改这段区间的```val```。最后把整个```set```遍历一边即可获得答案。 当然这题动态开点线段树也是可以的。 ``` #include<cstdio> #include<cctype> #include<set> #define LL long long using std::set; #define IT set<node>::iterator LL Read() { LL x=0;char c=getchar(); while(!isdigit(c)) { c=getchar(); } while(isdigit(c)) { x=x*10+(c^48); c=getchar(); } return x; } struct node { LL l,r; mutable int v; //由于需要修改,此处的v需要mutable修饰 node(LL L, LL R=-1, int V=0):l(L), r(R), v(V) {} bool operator<(const node& o) const { return l < o.l; } }; set<node> s; //split(pos)操作将原来含有pos位置的节点分成两部分:[l,pos−1]和[pos,r] IT split(LL pos) { IT it = s.lower_bound(node(pos)); if (it != s.end() && it->l == pos) return it; --it; LL L = it->l, R = it->r; LL V = it->v; s.erase(it); s.insert(node(L, pos-1, V)); return s.insert(node(pos, R, V)).first; //这里利用了pair<iterator,bool> insert (const value_type& val)的返回值 } void assign_val(LL l, LL r) { IT itr = split(r+1),itl = split(l); s.erase(itl, itr); //void erase (iterator first, iterator last)可删除[first,last)区间 s.insert(node(l, r, 1)); } LL sum(LL l, LL r) { //这个没啥好说的,遍历一遍 IT itr = split(r+1),itl = split(l); LL res = 0; for (; itl != itr; ++itl) res += itl->v ? itl->r - itl->l + 1 : 0; return res; } int main() { int n=Read(); LL l,r; s.insert(node(0,1e17+5)); //插入一个[0,1e17+5],值全部为0的区间 while(n--) { l=Read(); r=Read(); assign_val(l,r); } printf("%lld",sum(0,1e17+3)); return 0; } ```