题解:P11265 【模板】静态区间半群查询
简单的期望
首先按序列分块,分
然后处理
对于
同一块的情况,则暴力。
在同一块内的概率为
#include <bits/stdc++.h>
using namespace std;
struct mat {
int a[2][2];
mat() {
a[0][0] = a[1][1] = 0;
a[1][0] = a[0][1] = 0x3f3f3f3f;
}
mat(int x, int y, int z, int w) {
a[0][0] = x, a[0][1] = y, a[1][0] = z, a[1][1] = w;
}
friend bool operator == (mat x, mat y){
return x . a[0][0] == y . a[0][0] && x . a[0][1] == y . a[0][1] && x . a[1][1] == y . a[1][1] && x . a[1][0] == y . a[1][0];
}
};
mat mul(const mat& x, const mat& y) {
return {min(x.a[0][0] + y.a[0][0], x.a[0][1] + y.a[1][0]),
min(x.a[0][0] + y.a[0][1], x.a[0][1] + y.a[1][1]),
min(x.a[1][0] + y.a[0][0], x.a[1][1] + y.a[1][0]),
min(x.a[1][0] + y.a[0][1], x.a[1][1] + y.a[1][1])};
}
struct random {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
uint64_t rnd() {
sd ^= sd << 13, sd ^= sd >> 7;
return sd ^= sd << 17;
}
void init() { cin >> sd >> b, sd = splitmix64(sd); }
void genmat(mat& res) {
uint64_t val = rnd();
for (int i : {0, 1})
for (int j : {0, 1}) res.a[i][j] = val >> ((i << 1 | j) << 4) & 0xff;
}
void genqry(int& l, int& r, int n) {
if ((rnd() & 1) && b) {
int c = rnd() % (n - b);
l = rnd() % (n - c) + 1, r = l + c;
} else {
l = rnd() % n + 1, r = rnd() % n + 1;
if (l > r) swap(l, r);
}
}
uint64_t sd;
int b;
} rnd;
struct output {
int ans, kv[2][2];
void init() {
for (int i : {0, 1})
for (int j : {0, 1}) cin >> kv[i][j];
}
void setres(mat res) {
int tmp = 0;
for (int i : {0, 1})
for (int j : {0, 1}) tmp += res.a[i][j] ^ kv[i][j];
ans ^= tmp;
}
} out;
constexpr int N = 1e6 + 9;
int n, m, ans;
mat a[N] , res[N] , f[2002][2002];
int bl[N];
int tp[N] , ed[N];
mat s[2004][2004];
mat t[2004][2004];
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n >> m, rnd.init(), out.init();
const int B = sqrt(n + m);
for (int i = 1; i <= n; ++i) rnd.genmat(a[i]) , bl[i] = i / B + 1;
// 你可以在这里进行你所需要的初始化。
mat p;
for(int i = 1; i <= n; ++ i){
if(res[bl[i]] == p){
res[bl[i]] = a[i];
tp[bl[i]] = i;
ed[bl[i]] = i + B - 1;
ed[bl[i]] = min(ed[bl[i]] , n);
}
else res[bl[i]] = mul(res[bl[i]] , a[i]);
}
for(int i = 1; i <= n / B + 1; ++ i){
f[i][i] = res[i];
for(int j = i + 1; j <= n / B + 1; ++ j)
f[i][j] = mul(f[i][j - 1] , res[j]);
}
vector<int> cnt(B + 2);
mat empty;
for(int i = 1; i <= n; i ++){
cnt[bl[i]] ++;
s[bl[i]][cnt[bl[i]]] = mul(s[bl[i]][cnt[bl[i]] - 1] , a[i]);
}
for(int i = n; i >= 1; i --){
cnt[bl[i]] --;
t[bl[i]][cnt[bl[i]]] = mul(a[i] , t[bl[i]][cnt[bl[i]] + 1]);
}
for (int l, r; m; --m) {
rnd.genqry(l, r, n);
if(bl[r] == bl[l]){
out.setres(accumulate(a + l, a + r + 1, mat(), mul));
continue;
}
mat ans;
if(l != tp[bl[l]])
ans = t[bl[l]][l - tp[bl[l]]] , l = ed[bl[l]] + 1;
if(bl[l] == bl[r]){
out . setres(mul(ans , s[bl[l]][r - tp[bl[l]] + 1]));
continue;
}
int q = r;
if(q != bl[r]) q = tp[bl[r]] - 1;
ans = mul(ans , f[bl[l]][bl[q]]);
if(r != bl[r]) ans = mul(ans , s[bl[r]][r - tp[bl[r]] + 1]);
out.setres(ans);
// 你可以把上面这个 accumulate 改成自己的查询函数。
}
return cout << out.ans << endl, 0;
}