[2020 CCPC 威海 G] Caesar Cipher
https://codeforces.ml/gym/102798
题意:
给你一段序列,有两种操作。
- \(1\) \(l\) \(r\),对\([l, r]\)区间内所有数\(+1\)并\(mod\ 65536\)
- \(2\) \(x\) \(y\) \(l\),询问\([x, x + l]\) 是否与\([y, y + l]\)相等
题解:
考虑线段树。需要\(mod\ 65536\),看似不是很好操作,但其实你要从\(0\)加到\(65536\)的周期是比较长的,不会很频繁地更新很多点,所以我们就可以暴力去\(mod\ 65536\)。对于询问区间是否相等,我们可以用线段树来维护区间哈希值,最后取出来比较哈希值即可。
第一次遇到卡自然溢出的题目。卡哈希最重要的不是\(base\)值,而是模数,我们手动取模一下就能过了。保险的话也可以用双哈希维护,判断两种哈希值是否都相同。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int M = 65536;
const ll bas = 131;
const int N = 5e5 + 7;
ll gap[N];
int n, q, a[N], ql, qr, len, op;
struct Seg{
ll t[N << 2], base[N << 2], maxx[N << 2], lazy[N << 2];
void up(int id) {
base[id] = (base[id << 1] + base[id << 1| 1]) % mod;
t[id] = (t[id << 1] + t[id << 1 | 1]) % mod;
maxx[id] = max(maxx[id << 1], maxx[id << 1 | 1]);
}
void build(int id, int l, int r) {
t[id] = maxx[id] = base[id] = lazy[id] = 0;
if (l == r) {
base[id] = gap[l - 1];
maxx[id] = a[l];
t[id] = (ll)a[l] * base[id] % mod;
return;
}
int mid = l + r >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
up(id);
}
void down(int id) {
if (!lazy[id]) return;
ll tmp = lazy[id];
lazy[id] = 0;
lazy[id << 1] += tmp;
lazy[id << 1 | 1] += tmp;
maxx[id << 1] += tmp;
maxx[id << 1 | 1] += tmp;
t[id << 1] = (t[id << 1] + (base[id << 1] * tmp) % mod) % mod;
t[id << 1 | 1] = (t[id << 1 | 1] + (base[id << 1 | 1] * tmp) % mod) % mod;
}
void modify(int id, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr) {
lazy[id]++;
maxx[id]++;
t[id] = (t[id] + base[id]) % mod;
return;
}
down(id);
int mid = l + r >> 1;
if (ql <= mid) modify(id << 1, l, mid, ql, qr);
if (qr > mid) modify(id << 1 | 1, mid + 1, r, ql, qr);
up(id);
}
ll query(int id, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr) return t[id];
down(id);
ll res = 0;
int mid = l + r >> 1;
if (ql <= mid) res = (res + query(id << 1, l, mid, ql, qr)) % mod;
if (qr > mid) res = (res + query(id << 1 | 1, mid + 1, r , ql ,qr)) % mod;
return res;
}
void work(int id, int l, int r) {
if (maxx[id] < M) return;
if (l == r) {
maxx[id] %= M;
t[id] = base[id] * maxx[id] % mod;
return;
}
down(id);
int mid = l + r >> 1;
if (maxx[id << 1] >= M) work(id << 1, l, mid);
if (maxx[id << 1 | 1] >= M) work(id << 1 | 1, mid + 1, r);
up(id);
}
}seg;
bool ok() {
seg.work(1, 1, n);
scanf("%d %d %d", &ql, &qr, &len);
if (qr < ql) swap(ql, qr);
ll va = seg.query(1, 1, n, ql, ql + len - 1);
ll vb = seg.query(1, 1, n, qr, qr + len - 1);
va = va * gap[qr - ql] % mod;
return va == vb;
}
void solve() {
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
seg.build(1, 1, n);
for (int i = 1; i <= q; ++i) {
scanf("%d", &op);
if (op == 1) {
scanf("%d%d", &ql, &qr);
seg.modify(1, 1, n, ql, qr);
} else {
if (ok()) puts("yes");
else puts("no");
}
}
}
int main() {
gap[0] = 1;
for (int i = 1; i < N; ++i) {
gap[i] = gap[i - 1] * bas % mod;
}
solve();
return 0;
}
/*
5 6
1 2 1 2 1
2 1 2 2
2 1 3 3
1 1 1
1 3 5
2 1 2 4
2 1 2 2
*/

浙公网安备 33010602011771号