896C

ODT/珂朵莉树

原来这个东西很咸鱼,只能数据随机情况下nloglogn,不过作为卡常还是很好的

大概就是维护区间,值相同的并且连续当成一个区间存在set里,每次区间操作强行分裂就行了。

复杂度因为是随机保证

#include<bits/stdc++.h>
using namespace std;
int n, m, seed, mx;
int rnd() 
{
    int ret = seed;
    seed = (1LL * seed * 7 + 13) % 1000000007;
    return ret;
}
struct data {
    int l, r;
    long long x;
    data() {}
    data(int _, int __, long long ___) : l(_), r(__), x(___) {}
    bool friend operator < (const data &a, const data &b) {
        return a.l != b.l ? a.l < b.l : a.r < b.r;
    }
};
bool cmp(const data &a, const data &b) 
{
    return a.x < b.x;
}
set<data> s;
vector<data> buf;
void cut(int p) 
{
    set<data> :: iterator it = prev(s.upper_bound(data(p, n + 3, -1)));
    if(it -> l == p) return;
    data tmp = *it;
    s.erase(it);
    s.insert(data(tmp.l, p, tmp.x));
    s.insert(data(p, tmp.r, tmp.x));
}
void merge(int l, int r)
{
    cut(l);
    cut(r);
    buf.clear();
    for(set<data> :: iterator it = s.lower_bound(data(l, -1, -1)); it != s.end() && it -> r <= r; ++it) buf.push_back(*it);
}
long long power(long long x, long long t, long long P)
{
    long long ret = 1;
    x %= P;
    for(; t; t >>= 1, x = x * x % P) if(t & 1) ret = ret * x % P;
    return ret;
}
int main()
{
    scanf("%d%d%d%d", &n, &m, &seed, &mx);
    for(int i = 1; i <= n; ++i) s.insert(data(i, i + 1, rnd() % mx + 1));
    while(m--)
    {
        int opt = rnd() % 4 + 1, l = rnd() % n + 1, r = rnd() % n + 1;
        long long x, y;
        if(l > r) swap(l, r);
        if(opt == 3) x = (rnd() % (r - l + 1)) + 1;
        else x = rnd() % mx + 1;
        if(opt == 4) y = rnd() % mx + 1;
        merge(l, r + 1);
        if(opt == 1) 
        {
            for(int i = 0; i < buf.size(); ++i) 
            {
                s.erase(buf[i]);
                s.insert(data(buf[i].l, buf[i].r, buf[i].x + x));
            }
        }
        if(opt == 2)
        {
            for(int i = 0; i < buf.size(); ++i) s.erase(buf[i]);
            s.insert(data(l, r + 1, x));
        }
        if(opt == 3)
        {
            sort(buf.begin(), buf.end(), cmp);
            --x;
            for(int i = 0; i < buf.size(); ++i) 
            {
                if(x < buf[i].r - buf[i].l) 
                {
                    printf("%lld\n", buf[i].x);
                    break;
                }
                else x -= buf[i].r - buf[i].l;
            }
        }
        if(opt == 4)
        {
            long long ans = 0;
            for(int i = 0; i < buf.size(); ++i) ans = (ans + power(buf[i].x, x, y) * (long long)(buf[i].r - buf[i].l) % y) % y;
            printf("%lld\n", (ans % y + y) % y);
        }
    }
    return 0;
}
View Code

 

posted @ 2017-12-04 18:32  19992147  阅读(218)  评论(0编辑  收藏  举报