[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;
}

浙公网安备 33010602011771号