CF 896C Willem, Chtholly and Seniorious

题目描述

https://codeforces.com/problemset/problem/896/C

简要题意:给定一个长度为 $n$ 的序列 $a_i$,现在有 $m$ 个操作,操作有四种,第一种操作给定区间 $[l,r]$ 和权值 $v$,将 $[l,r]$ 所有数加上 $v$;第二种操作给定区间 $[l,r]$ 和权值 $v$,将 $[l,r]$ 内所有数变成 $v$;第三种操作给定区间 $[l,r]$ 和 $k$,求 $[l,r]$ 内第 $k$ 小的数;第四种操作给定区间 $[l,r]$ 和 $x,y$,求 $(\sum_{i=1}^na_i^k)\bmod y$

$n,m\le 10^5$,数据随机

Solution

因为数据随机,所以我们直接使用珂朵莉树维护权值相同的段即可,据说随机数据情况下,只有 $O(\log \log n)$ 段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#define maxn 100010
#define ll long long
using namespace std;

ll pow_mod(ll x, ll n, int p) {
ll s = 1;
for (; n; n >>= 1, x = x * x % p)
if (n & 1) s = s * x % p;
return s;
}

struct Chtolly {
int l, r;
mutable ll v;

Chtolly(int l = 0, int r = 0, ll v = 0) : l(l), r(r), v(v) {}
friend bool operator < (const Chtolly &u, const Chtolly &v) { return u.l < v.l; }
}; set<Chtolly> S;

set<Chtolly>::iterator split(int k) {
auto it = S.lower_bound(Chtolly(k));
if (it != S.end() && it -> l == k) return it;
it = prev(it); Chtolly t = *it;
if (it -> r < k) return S.end();
return S.erase(it), S.emplace(t.l, k - 1, t.v), S.emplace(k, t.r, t.v).first;
}

void assign(int l, int r, int v) {
auto itr = split(r + 1), itl = split(l);
S.erase(itl, itr);
S.emplace(l, r, v);
}

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

ll query_rk(int l, int r, int k) {
auto itr = split(r + 1), itl = split(l);
vector<pair<ll, int>> vec;
for (auto it = itl; it != itr; ++it)
vec.emplace_back(it -> v, it -> r - it -> l + 1);
sort(vec.begin(), vec.end());
for (auto [v, cnt] : vec) {
if (k <= cnt) return v;
k -= cnt;
} return 0;
}

ll query_sum(int l, int r, int k, int p) {
auto itr = split(r + 1), itl = split(l);
ll ans = 0;
for (auto it = itl; it != itr; ++it)
ans = (ans + (it -> r - it -> l + 1) * pow_mod(it -> v % p , k, p)) % p;
return ans;
}

int seed, vmax; const int p = 1000000007;
inline int Rand() {
int res = seed;
seed = (seed * 7ll + 13) % p;
return res;
}

int n, m, a[maxn];

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);

cin >> n >> m >> seed >> vmax;
for (int i = 1; i <= n; ++i) {
a[i] = Rand() % vmax + 1;
S.emplace(i, i, a[i]);
}
for (int i = 1; i <= m; ++i) {
int opt = Rand() % 4 + 1, l = Rand() % n + 1, r = Rand() % n + 1, x, y;
if (l > r) swap(l, r);
if (opt == 3) x = Rand() % (r - l + 1) + 1;
else x = Rand() % vmax + 1;
if (opt == 4) y = Rand() % vmax + 1;

if (opt == 1) add(l, r, x);
else if (opt == 2) assign(l, r, x);
else if (opt == 3) cout << query_rk(l, r, x) << "\n";
else cout << query_sum(l, r, x, y) << "\n";
}
return 0;
}