P3792 由乃與大母神原型和偶像崇拜

Saltyfish6發表於2024-03-22

隨機賦權雜湊,算是板子題?

主要是想記錄隨機賦權 \(\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;
}

相關文章