BZOJ 1858 [SCOI2010] 序列操作

本来想用线段树做,但是考虑到用线段树的话pushup,pushdown函数有点复杂... 看到题目有覆盖操作立刻想到了珂朵莉树,于是现学了一波然后改了一下模板A了这道题。 (珂学是个好东西) (刷这道题全程循环夢違科(珂)学世紀2333333)

    
    #include <iostream>
    #include <set>
    #include <vector>
    #include <algorithm>
    #include <cstdio>
    
    #define __node_it set<node>::iterator
    
    using namespace std;
    
    //define
    const int maxn = 1e5 + 5;
    struct node{
        mutable int l, r, v;
        node(int L,int R = -1, int V = 0):l(L), r(R), v(V){}
        bool operator < (const node& rhs) const{
            return l < rhs.l;
        }
    };
    int n, m;
    set<node> s;
    
    __node_it split(int rt){
        __node_it it = s.lower_bound(node(rt));
        if(it != s.end() && it->l == rt)return it;
        --it;int ll = it->l, rr = it-> r, vv = it->v;
        s.erase(it);
        s.insert(node(ll, rt - 1, vv));
        return s.insert(node(rt, rr, vv)).first;
    }
    
    void assign(int l, int r, int v){
        __node_it itr = split(r + 1), itl = split(l);
        s.erase(itl, itr);
        s.insert(node(l, r, v));
    }
    
    int sum(int l, int r){
        int ans = 0;
        __node_it itr = split(r + 1), itl = split(l);
        for(; itl != itr; ++itl){
            ans += itl->v ? itl->r - itl->l + 1:0;
        }
        return ans;
    }
    
    void reverse(int l, int r){
        __node_it itr = split(r + 1), itl = split(l);
        for(; itl != itr; ++itl){
            itl->v ^= 1;
        }
    }
    
    int cnt(int l, int r){
        int ans = -0x7f7f7f7f, cnt = 0;
        __node_it itr = split(r + 1), itl = split(l);
        for(; itl != itr; ++itl){
            if(itl->v == 1){
                cnt += itl->r - itl->l + 1;
            }
            else{
                cnt = 0;
            }
            ans = max(ans, cnt);
        }
        return ans;
    }
    
    //main
    int main(){
        ios::sync_with_stdio(false);
        cin >> n >> m;int tmp;
        for(register int i = 0; i < n; ++i){
            cin >> tmp;
            s.insert(node(i, i, tmp));
        }
        int x, y, z, a;
        while(m--){
            cin >> x;
            switch(x){
                case 0:
                    cin >> y >> z;
                    assign(y, z, 0);
                    break;
                case 1:
                    cin >> y >> z;
                    assign(y, z, 1);
                    break;
                case 2:
                    cin >> y >> z;
                    reverse(y, z);
                    break;
                case 3:
                    cin >> y >> z;
                    cout << sum(y, z) << endl;
                    break;
                case 4:
                    cin >> y >> z;
                    cout << cnt(y, z) << endl;
                    break;
            }
        }
        return 0;
    }