9.20 Magical multisets

The meaning of problems

There \ (n-\) th re-set number \ (. 1 \ to n-\) , are empty at the start, there are two operations

  • The element \ (X \) was added numbered \ ([l, r] \ ) of a set, if there are elements in the original set \ (X \) , then the set of all elements are double the number of
  • Inquiry number \ ([l, r] \ ) number of elements in the set and, modulo \ (998,244,353 \)


solution

\ (set \) maintenance interval

For each color to open a \ (SET \) , storage section (left point, right point)

Each time a section is added, to carry out cross-section by, the corresponding line segment tree sections which \ (2 \) operation; for otherwise empty section, a section for adding the corresponding interval \ (1 \) operation

In order to ensure the complexity of each section should be merged (It may be noted here that we only pay attention to whether the interval \ (x \) this number, so you can direct the combined interval length)

Very clever ah, the first exposure to this topic

Code

#include <set>
#include <cstdio>

using namespace std;

const int N = 4e5 + 10;
const int mod = 998244353;

int read();

struct seg {
    int l, r;
    seg(int _l, int _r) : l(_l), r(_r) {}
    bool operator < (const seg& _t) const { return r < _t.r; }
};

int n, q;

set<seg> st[N];
typedef set<seg>::iterator iter;

struct SegTree {
#define ls(x) x << 1    
#define rs(x) x << 1 | 1
    
    struct node {
        int val, add, mul;
        node() : val(0), add(0), mul(1) {}
    } t[N << 2];
    
    void addtag(int x, int l, int r, int v) {
        t[x].val = (t[x].val + 1LL * (r - l + 1) * v % mod) % mod;
        t[x].add = (t[x].add + v) % mod;
    }
    
    void multag(int x, int l, int r, int v) {
        t[x].val = 1LL * t[x].val * v % mod;
        t[x].add = 1LL * t[x].add * v % mod;        
        t[x].mul = 1LL * t[x].mul * v % mod;
    }
    
    void pushdown(int x, int l, int r) {
        int mid = l + r >> 1;
        if (t[x].mul != 1) {
            multag(ls(x), l, mid, t[x].mul);
            multag(rs(x), mid + 1, r, t[x].mul);
            t[x].mul = 1;
        }
        if (t[x].add) {
            addtag(ls(x), l, mid, t[x].add);
            addtag(rs(x), mid + 1, r, t[x].add);
            t[x].add = 0;   
        }
    }
    
    void modify(int x, int l, int r, int ql, int qr, int fl, int v) {
        if (ql <= l && r <= qr) 
            return (!fl) ? addtag(x, l, r, v) : multag(x, l, r, v), void();
        int mid = l + r >> 1;
        pushdown(x, l, r);
        if (ql <= mid)
            modify(ls(x), l, mid, ql, qr, fl, v);
        if (qr > mid)
            modify(rs(x), mid + 1, r, ql, qr, fl, v);
        t[x].val = (t[ls(x)].val + t[rs(x)].val) % mod; 
    }
    
    int query(int x, int l, int r, int ql, int qr) {
        if (ql <= l && r <= qr)
            return t[x].val;
        int mid = l + r >> 1, res = 0;
        pushdown(x, l, r);
        if (ql <= mid)  
            res = (res + query(ls(x), l, mid, ql, qr)) % mod;
        if (qr > mid)
            res = (res + query(rs(x), mid + 1, r, ql, qr)) % mod;
        return res;
    }

#undef ls
#undef rs
} tr;

void update(int L, int R, int x) {
    iter it = st[x].lower_bound(seg(L, L));
    
    if (it == st[x].end() || (it -> l) > R) {
        tr.modify(1, 1, n, L, R, 0, 1);
        st[x].insert(seg(L, R));
        return;
    }
    
    if ((it -> l) <= L && (it -> r) >= R) {
        tr.modify(1, 1, n, L, R, 1, 2);
        return;
    }
    
    iter bg = it;
    int sl = L;
    while (it != st[x].end() && (it -> l) <= R) {
        if ((it -> l) > sl)
            tr.modify(1, 1, n, sl, (it -> l) - 1, 0, 1);
        tr.modify(1, 1, n, max(it -> l, L), min(it -> r, R), 1, 2);
        sl = (it -> r) + 1;
        ++it;
    }
    --it;
    
    if (sl <= R)
        tr.modify(1, 1, n, sl, R, 0, 1);    
    
    seg New = seg(min(L, bg -> l), max(R, it -> r));
    while (bg != it)
        st[x].erase(bg++);
    st[x].erase(it);
    
    st[x].insert(New);
}

int main() {
    
//  freopen("multiset.in", "r", stdin);
//  freopen("multiset.out", "w", stdout);
    
    n = read(), q = read();

    int op, l, r;   
    while (q--) {
        op = read(), l = read(), r = read();
        if (op == 1)
            update(l, r, read());
        else
            printf("%d\n", tr.query(1, 1, n, l, r));
    }
    
    return 0;
}

#define gc getchar
int read() {
    int x = 0, c = gc();    
    while (c < '0' || c > '9')    c = gc();
    while (c >= '0' && c <= '9')  x = x * 10 + c - 48, c = gc();
    return x;
}

Guess you like

Origin www.cnblogs.com/VeniVidiVici/p/11564387.html