社区讨论

DSU on Tree 求条

学术版参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mhjaqz5n
此快照首次捕获于
2025/11/03 23:30
4 个月前
此快照最后确认于
2025/11/03 23:30
4 个月前
查看原帖
具体的,题目是求满足 maxi=lraii=lrai\max_{i = l}^{r} a_i \ge \oplus_{i = l}^{r} a_i 的区间 (l, r) 个数,思路是 Trie + 笛卡尔 + DSU on Tree
CPP
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
typedef pair<int, int> pi;
typedef unsigned long long ull;
#define endl '\n'
int n, p, m;
struct node {
	ll hs[N], fp[N], pri, mod;
	void init (int a[], int x, int y) {
		fp[0] = 1;
		pri = x, mod = y;
		for (int i = 1; i <= n; i ++) {
			hs[i] = (hs[i - 1] * pri % mod + a[i]) % mod;
			fp[i] = fp[i - 1] * pri % mod;
		}
	}
	ll f (int l, int r) {
		return (hs[r] - hs[l - 1] * fp[r - l + 1] % mod + mod) % mod;
	}
}h, h1, h2;
int a[N];
int cnt[50000000];

signed main() {
	freopen("collision.in", "r", stdin);
	freopen("collision.out", "w", stdout);
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n >> p >> m;
	for (int i = 1; i <= n; i ++) cin >> a[n - i + 1];
	h.init(a, p, m);
	h1.init(a, 131, 998244853);
	h2.init(a, 131, 998244353);
	if (m <= 5e7) {
		ll ans = 0;
		for (int len = 1; len <= n; len ++) {
			for (int i = 1, j = len; j <= n; i ++, j ++) {
				ans += cnt[h.f(i, j)], cnt[h.f(i, j)] ++;
			}
			vector<pi> v;
			for (int i = 1, j = len; j <= n; i ++, j ++)
				v.push_back({h1.f(i, j), h2.f(i, j)});
			sort (v.begin(), v.end());
			pi lst = {-1, -1};
			int r = 0;
			for (pi x : v) {
				if (x != lst) ans -= (r - 1) * r / 2, lst = x, r = 1;
				else r ++;
			}
			ans -= (r - 1) * r / 2;
		}
		cout << ans * 2 << endl;
	} else {
		ll ans = 0;
		vector<int> ve;
		for (int len = 1; len <= n; len ++) {
			for (int i = 1, j = len; j <= n; i ++, j ++) ve.push_back(h.f(i, j));
			vector<pi> v;
			for (int i = 1, j = len; j <= n; i ++, j ++)
				v.push_back({h1.f(i, j), h2.f(i, j)});
			sort (v.begin(), v.end());
			pi lst = {-1, -1};
			int r = 0;
			for (pi x : v) {
				if (x != lst) ans -= (r - 1) * r / 2, lst = x, r = 1;
				else r ++;
			}
			ans -= (r - 1) * r / 2;
		}
		sort (ve.begin(), ve.end());
		int lst = -1, r = 0;
		for (int x : ve) {
			if (x != lst) ans += 1ll * (r - 1) * r / 2, lst = x, r = 1;
			else r ++;
		}
		ans += 1ll * (r - 1) * r / 2;
		cout << ans * 2 << endl;
	}
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...