Loading

[CodeForces 452F] Permutation

题意

给定一个长度为 \(n\) 的排列 \(p\),判断是否存在长度为 \(3\) 的等差数列。

数据范围:\(1\le n\le 3\times 10^5\)

思路

考虑枚举中间的元素 \(x\),暴力枚举 \(k\),并判断 \(x-k\) 的位置小于 \(i\)\(x+k\) 的位置大于 \(i\);或 \(x+k\) 的位置小于 \(i\)\(x-k\) 的位置大于 \(i\)。暴力判断的时间复杂度为 \(O(n^2)\)

考虑 \(x-k\)\(x+k\) 实际上是在进行回文判断,所以如果令 \(i\) 左侧的数为 \(0\)\(i\) 右侧的数为 \(1\),则只要不是回文串,那么便说明存在。每一次的更新操作相当于将 \(p_i\)\(1\)\(0\),每次判断区间是否是回文串,可采用哈希的方式实现。使用线段树,即可做到 \(O(n\log n)\)

代码

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
using i64 = long long;
using u64 = unsigned i64;

const int maxn = 300005, mod = 998244353, base = 233;

int n;
int p[maxn], pw1[maxn];
u64 pw2[maxn];
struct node {
	int l, r;
	pair<int, u64> H1, H2;
}tr[maxn * 4];
node operator+ (node a, node b) {
	node c;
	c.l = a.l, c.r = b.r;
	c.H1.fi = (a.H1.fi + (i64)b.H1.fi * pw1[a.r - a.l + 1] % mod) % mod;
	c.H2.fi = (b.H2.fi + (i64)a.H2.fi * pw1[b.r - b.l + 1] % mod) % mod;
	c.H1.se = a.H1.se + b.H1.se * pw2[a.r - a.l + 1];
	c.H2.se = b.H2.se + a.H2.se * pw2[b.r - b.l + 1];
	return c;
}

void build(int u, int l, int r) {
	if (l == r) {
		tr[u] = {l, r, {1, 1}, {1, 1}};
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	tr[u] = tr[u << 1] + tr[u << 1 | 1];
}

void update(int u, int x) {
	if (tr[u].l == tr[u].r) {
		tr[u] = {tr[u].l, tr[u].r, {0, 0}, {0, 0}};
		return;
	}
	int mid = tr[u].l + tr[u].r >> 1;
	if (mid >= x) update(u << 1, x);
	else update(u << 1 | 1, x);
	tr[u] = tr[u << 1] + tr[u << 1 | 1];
}

node query(int u, int l, int r) {
	if (tr[u].l >= l && tr[u].r <= r) return tr[u];
	int mid = tr[u].l + tr[u].r >> 1;
	if (mid >= l && mid < r) return query(u << 1, l, r) + query(u << 1 | 1, l, r);
	else if (mid >= l) return query(u << 1, l, r);
	else return query(u << 1 | 1, l, r);
}

int main() {
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);

	cin >> n;
	for (int i = 1; i <= n; i ++)
		cin >> p[i];

	pw1[0] = pw2[0] = 1;
	for (int i = 1; i <= n; i ++) {
		pw1[i] = (i64)pw1[i - 1] * base % mod;
		pw2[i] = pw2[i - 1] * base;
	}

	build(1, 1, n);

	for (int i = 1; i <= n; i ++) {
		update(1, p[i]);
		int len = min(p[i] - 1, n - p[i]);
		auto temp = query(1, p[i] - len, p[i] + len);
		if (temp.H1 != temp.H2) {
			cout << "YES" << endl;
			return 0;
		}
	}

	cout << "NO" << endl;

	return 0;
}
posted @ 2025-04-10 11:33  Pigsyy  阅读(20)  评论(0)    收藏  举报