Loading

[模板] ODT-老司机树 CodeForces-896C

[模板] ODT-老司机树 CodeForces-896C

适用于随机数据 ,区间赋值。

核心思想,把值相同的区间合并成一个结点保存在set里。

结点保存

struct node {
    int l, r;
    mutable ll v;
    node(int _l,int _r = -1,ll _v = 0):l(_l),r(_r),v(_v){}
    bool operator < (const node& b) const {
        return l < b.l;
    }
};

mutable 的含义是“可变的”,让我们可以在后续操作中修改v的值。

这意味着我们可以直接修改以及插入的set的元素的v值,而不用将元素取出再插入

核心操作

split

它用于将原本包含点x的区间\([l,r]\) 分裂为两个区间\([l,x),[x,r]\) 并且返回后者的迭代器

auto split(int pos) {
    auto it = s.lower_bound(node(pos));
    if (it != s.end() && it->l == pos) return it;
    --it;
    if (pos > it->r) return s.end();
    int 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;
}

assign

可以使ODT的大小大大减小

void assign(int l, int r, ll val = 0) {
    auto itr = split(r + 1), itl = split(l);
    s.erase(itl, itr);
    s.insert(node(l, r, val));
}

其他

套模板就好了

代码

struct node {
    int l, r;
    mutable ll v;
    node(int _l,int _r = -1,ll _v = 0):l(_l),r(_r),v(_v){}
    bool operator < (const node& b) const {
        return l < b.l;
    }
};

set<node> s;
vector<pii> v;

auto split(int pos) {
    auto it = s.lower_bound(node(pos));
    if (it != s.end() && it->l == pos) return it;
    --it;
    if (pos > it->r) return s.end();
    int 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;
}

void add(int l, int r, ll val = 1) {
    auto itr = split(r + 1), itl = split(l);
    for (; itl != itr; itl++) itl->v += val;
}

void assign(int l, int r, ll val = 0) {
    auto itr = split(r + 1), itl = split(l);
    s.erase(itl, itr);
    s.insert(node(l, r, val));
}

ll get_rank(int l, int r, int k, bool reversed = 0) {
    if (reversed) k = r - l + 2 - k;
    auto itr = split(r + 1), itl = split(l);
    v.clear();
    for (; itl != itr; itl++)
        v.push_back(make_pair(itl->v, itl->r - itl->l + 1));
    sort(v.begin(), v.end());
    for (auto i : v) {
        k -= i.second;
        if (k <= 0) return i.first;
    }
    return -1;
}

ll sum(int l, int r, int ex, int mod) {
    auto itr = split(r + 1), itl = split(l);
    ll res = 0;
    for (; itl != itr; itl++)
        res += (ll)(itl->r - itl->l + 1) % mod * ksm(itl->v,(ll) ex,(ll) mod) % mod, res %= mod;
    return res;
}

int n, m;
ll seed, vm;


ll rad() {
    ll res = seed;
    seed = (seed * 7 + 13) % 1000000007;
    return res;
}

int main() {
    int op, l, r;
    int x, y;
    n = readint(), m = readint(), seed = readll(), vm = readll();
    for (int i = 1; i <= n; i++) {
        ll tmp = (rad() % vm) + 1;
        s.insert(node(i, i, tmp));
    }
    while (m--) {
        op = (rad() % 4) + 1;
        l = (rad() % n) + 1;
        r = (rad() % n) + 1;
        if (l > r) swap(l, r);
        if (op == 3) x = (rad() % (r - l + 1)) + 1;
        else x = (rad() % vm) + 1;
        if (op == 4) y = (rad() % vm) + 1;
        if (op == 1) add(l, r, x);
        else if (op == 2) assign(l, r, x);
        else if (op == 3) Put(get_rank(l, r, x)), uts("");
        else {
            Put(sum(l, r, x, y)), puts("");
        }
    }
}
posted @ 2020-09-02 00:12  MQFLLY  阅读(139)  评论(0编辑  收藏  举报