• 【cf915】E. Physical Education Lessons(线段树)


    传送门

    简单的线段树区间修改区间查询,但是因为数据范围过大,所以采用动态开点的方法(注意一下空间问题)。
    也可以直接对询问区间的端点离散化然后建树,这种方法时间复杂度和空间复杂度都比较优秀。
    给出动态开点的代码:

    /*
     * 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;
    }
    
  • 相关阅读:
    leetcode 买卖股票的最佳时机3
    leetcode 买卖股票的最佳时机Ⅱ
    leetcode 最长有效括号
    C++中的%lld和%I64d区别
    Ural 1095 Nikifor 3 思维+同余性质的利用
    博弈基础
    ural 1091. Tmutarakan Exams
    容斥原理
    一些易错的地方
    codeforces911D Inversion Counting 求逆序数+小trick
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11845796.html
Copyright © 2020-2023  润新知