P2757 [国家集训队] 等差子序列
很有意思的题。
首先把等差数列的长度变为 \(3\),得到大幅简化。
然后考虑第一项和第三项值域上关于中间项对称。于是我们枚举中间项 \(a_i\),看看是否存在 \(a_i - k\) 在其左侧,\(a_i + k\) 在其右侧的情况。我们从左到右考虑每个 \(i\) 的话,就要求着 \(a_i - k\) 之前出现过而 \(a_i + k\) 没有出现过,因为如果 \(a_i + k\) 没有出现过就说明其在右侧。考虑刻画这个东西,出现过的数视为 \(1\),没出现过视为 \(0\),则要求存在 \(a_i - k\) 的位置是 \(1\),\(a_i + k\) 的位置是 \(0\),这就意味着将这个 \(01\) 串在处 \(a_i\) 翻折,会有一个位置有 \(1\) 也有 \(0\)。其实就是设 \(len = \min(a_i, n - a_i + 1)\),那么 \([a_i - len + 1, a_i + len - 1]\) 不是一个回文串。使用线段树维护哈希即可,时间复杂度的 \(\mathcal{O}(n \log n)\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128 i128;
typedef pair<int, int> pii;
const int N = 5e5 + 10, bas = 131;
template<typename T>
void dbg(const T &t) { cout << t << endl; }
template<typename Type, typename... Types>
void dbg(const Type& arg, const Types&... args) {
cout << arg << ' ';
dbg(args...);
}
namespace Loop1st {
int n, a[N];
ull pw[N];
struct Node {
ull h1, h2;
int len;
Node operator + (const Node &A) const {
return {h1 * pw[A.len] + A.h1, pw[len] * A.h2 + h2, len + A.len};
}
} tr[N << 2];
struct SegTree {
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
void build(int l = 1, int r = n, int u = 1) {
if (l == r) { tr[u].h1 = tr[u].h2 = 0; tr[u].len = 1; return ; }
build(l, mid, ls); build(mid + 1, r, rs);
tr[u] = tr[ls] + tr[rs];
}
void add(int x, int l = 1, int r = n, int u = 1) {
if (l == r) { tr[u].h1 = tr[u].h2 = 1; return ; }
if (x <= mid) add(x, l, mid, ls);
else add(x, mid + 1, r, rs);
tr[u] = tr[ls] + tr[rs];
}
Node ask(int x, int y, int l = 1, int r = n, int u = 1) {
if (x <= l && r <= y) return tr[u];
if (y <= mid) return ask(x, y, l, mid, ls);
if (mid < x) return ask(x, y, mid + 1, r, rs);
return ask(x, y, l, mid, ls) + ask(x, y, mid + 1, r, rs);
}
} sgt;
void main() {
cin >> n;
pw[0] = 1;
for (int i = 1; i <= n; i++) pw[i] = pw[i - 1] * bas;
sgt.build();
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
sgt.add(a[i]);
int len = min(a[i], n - a[i] + 1);
auto [h1, h2, _] = sgt.ask(a[i] - len + 1, a[i] + len - 1);
if (h1 != h2) {
cout << "Y\n";
return ;
}
}
cout << "N\n";
}
}
int main() {
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--) Loop1st::main();
return 0;
}

浙公网安备 33010602011771号