隨機賦權雜湊,算是板子題?
主要是想記錄隨機賦權 \(\text{hash}\) 這個 \(\text{trick}\)。
顯然,我們可以透過找到 \([l,r]\) 中的最小值 \(\text{min}\),從而確定,這連續的一段權值是 \([\text{min},\text{min}+r-l]\)。
我們考慮如何去判斷。
顯然有一個簡單的想法,就是對於 \([1,2.5\times 10^7]\) 中的每一個數,隨機賦一個雜湊權值 \(\text{val}_i\),然後維護一個 \(\text{sum}_i\) 表示 \(\text{sum}_i=\sum_{j=1}^{i} \text{val}_j\)。
然後我們考慮維護每一個區間的 \(\sum \text{val}_i,i\in[l,r]\)。
由於存在修改,考慮線段樹維護這一過程,包括上面的區間最小值。
顯然,我們最後只需要判斷,\(\text{sum}_{\text{min}+r-l}-sum_{\text{min}-1}\) 是否與 \(\sum \text{val}_i,i\in[l,r]\) 相等即可。
由於是賦權,就會導致重複的機率極小,即使存在,你也可以透過選一個次數 \(k\), \(\text{sum}_i=\sum_{j=1}^{i} \text{val}_j^k\) 來減少錯誤的機率。
反正就是亂搞就能過。
#include <bits/stdc++.h>
using namespace std;
#define maxn 500005
#define maxe (int)(2.5e7)
int n, m;
int a[maxn], val[maxe + 5];
long long sum[maxe + 5];
struct segmentree
{
int l, r;
long long data;
int minn;
}tree[maxn << 2];
void update(int p)
{
tree[p].data = tree[p << 1].data + tree[p << 1 | 1].data;
tree[p].minn = min(tree[p << 1].minn, tree[p << 1 | 1].minn);
}
void build(int p, int l, int r)
{
tree[p].l = l, tree[p].r = r;
if(l == r) return tree[p].data = val[a[l]], tree[p].minn = a[l], void(0);
int mid = (l + r) >> 1;
build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
update(p);
}
void change(int p, int x, int y)
{
if(tree[p].l > x || tree[p].r < x) return;
if(tree[p].l == tree[p].r) return tree[p].data = val[y], tree[p].minn = y, void(0);
change(p << 1, x, y), change(p << 1 | 1, x, y);
update(p);
}
pair<long long, int> query(int p, int l, int r)
{
if(tree[p].l > r || tree[p].r < l) return make_pair(0, INT_MAX);
if(tree[p].l >= l && tree[p].r <= r) return make_pair(tree[p].data, tree[p].minn);
pair<long long, int> now1 = query(p << 1, l, r), now2 = query(p << 1 | 1, l, r);
return make_pair(now1.first + now2.first, min(now1.second, now2.second));
}
int main()
{
srand(time(NULL));
for (int i = 1; i <= maxe; ++i) val[i] = rand() % (long long)(1e11), sum[i] = sum[i - 1] + val[i];
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
build(1, 1, n);
while(m--)
{
int op, x, y;
scanf("%d %d %d", &op, &x, &y);
if(op == 1) change(1, x, y);
else
{
pair<long long, int> ans = query(1, x, y);
if(ans.second + (y - x) <= maxe && sum[ans.second + y - x] - sum[ans.second - 1] == ans.first) puts("damushen");
else puts("yuanxing");
}
}
return 0;
}