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; }