「LibreOJ β Round」ZQC 的截图(随机+hash)
暴力的做法就是可持久化线段树,可惜空间爆了。
考虑给每个颜色随机一个权值,若到根路径的权值和是3的倍数,则说明这条路径可能所有颜色的出现次数是3的倍数。
一次的错误率是\(1/3\),显然太高了。
但我们可以多搞几维,把权值变成了\(w\)维的向量,则正确率是\((1-{1\over 3^w})^m\)。
对于查询一个的,可以预先把每个颜色的1、2次的向量丢进一个hash表,每次查询即可,正确率\((1-{n\over 3^w})^m\)
\(w\)取\(16*3\)时,可以用三个int压位存向量,可以预处理\(3^6*3^6\)的转移矩阵以加速向量不进位加法。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
#define gc getchar
template<class T> void read(T &x) {
char c = ' '; x = 0; int f = 1;
while((c < '0' || c > '9') && c != '-') c = gc();
if(c == '-') f = -1, c = gc();
for(; c >= '0' && c <= '9'; c = gc()) x = x * 10 + c - '0';
x *= f;
}
const int w = 729;
int a3[7];
int ja[w][w];
struct P {
int x, y, z;
P(int _x = 0, int _y = 0, int _z = 0) {
x = _x, y = _y, z = _z;
}
};
void build() {
a3[0] = 1; fo(i, 1, 6) a3[i] = a3[i - 1] * 3;
ff(i, 0, w) ff(j, 0, w) {
int s = 0;
ff(k, 0, 6) {
int x = (i / a3[k] % 3 + j / a3[k] % 3) % 3;
s += x * a3[k];
}
ja[i][j] = s;
}
}
int calc(int x, int y) {
return ja[x / w / w][y / w / w] * w * w + ja[x / w % w][y / w % w] * w + ja[x % w][y % w];
}
P operator + (P a, P b) {
return P(calc(a.x, b.x), calc(a.y, b.y), calc(a.z, b.z));
}
bool operator == (P a, P b) {
return a.x == b.x && a.y == b.y;
}
int rd() {
return rand() % w * w * w + rand() % w * w + rand() % w;
}
const int N = 2e6 + 5;
int n, m;
P f[N], g[N * 2];
const int M = 7260718;
int h[M];
int ha(P a) {
int y = (a.x + a.y) % M;
while(h[y] != 0 && !(f[h[y]] == a))
y = (y + 1) % M;
return y;
}
int main() {
srand(time(0) + clock());
build();
scanf("%d %d", &n, &m);
fo(i, 1, n) {
f[i] = P(rd(), rd(), rd());
f[n + i] = f[i] + f[i];
int y = ha(f[i]);
h[y] = i;
y = ha(f[n + i]);
h[y] = n + i;
}
int ans = 0;
fo(i, 1, m) {
int x, y;
read(x); read(y);
x ^= ans, y ^= ans;
g[i] = g[y] + f[x];
if(g[i].x == 0 && g[i].y == 0) {
ans = -1;
} else {
int y = ha(g[i]);
if(h[y]) {
ans = h[y] > n ? h[y] - n : h[y];
} else ans = -2;
}
pp("%d\n", ans);
}
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址