专栏文章
题解:P2757 [国家集训队] 等差子序列
P2757题解参与者 3已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mip5hmkz
- 此快照首次捕获于
- 2025/12/03 06:29 3 个月前
- 此快照最后确认于
- 2025/12/03 06:29 3 个月前
给定你一个长度为 的排列 ,求是否存在 ,使得 构成一个等差数列。。
考虑枚举 ,以及公差 。
那么就有 在 的左右边出现。
我们考虑一个数组 ,如果 在 的左边,,否则为 。
则原命题变换为,枚举 ,存在公差 ,使得 。
考虑这个命题的否命题,枚举 ,对于任意的公差 ,都有 。
此时可以发现,如果对于一个 来说,满足否命题,就意味着数组 以 为中心是一个回文串。
现在问题就变成了,有一个 序列,每次操作询问两个一正一反长度一样的串是否相等,或者修改一个位置上的值(枚举 的所需改变)。
一般而言,检验串相等的方法是哈希,我们也考虑哈希。
于是我们只需要用线段树维护区间哈希值即可。
CPP// Problem: P2757 [国家集训队] 等差子序列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2757
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// 这回只花了 1s 就打完了。
// 真好。记得多手造几组。最好有暴力对拍。
#include <bits/stdc++.h>
#define upp(a, x, y) for (int a = x; a <= y; a++)
#define dww(a, x, y) for (int a = x; a >= y; a--)
#define pb(x) push_back(x)
#define endl '\n'
#define x first
#define y second
#define PII pair<int, int>
using namespace std;
const int N = 5e5 + 10;
struct node {
int l, r, hash, rhash;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define hash(x) tr[x].hash
#define rhash(x) tr[x].rhash
};
int n, a[N];
node tr[N * 4];
const int P = 1e9 + 9, B = 131;
int ms[N];
void pu(int x) {
int l = l(x), r = r(x);
int mid = l + r >> 1;
hash(x) = (1ll * hash(x * 2) * ms[r - mid] % P + hash(x * 2 + 1)) % P;
rhash(x) =
(1ll * rhash(x * 2 + 1) * ms[mid - l + 1] % P + rhash(x * 2)) % P;
}
void build(int x, int l, int r) {
l(x) = l, r(x) = r;
if (l == r) {
hash(x) = rhash(x) = 1;
return;
}
int mid = l + r >> 1;
build(x * 2, l, mid);
build(x * 2 + 1, mid + 1, r);
pu(x);
}
void init() {
ms[0] = 1;
upp(i, 1, N - 1) ms[i] = (1ll * ms[i - 1] * B) % P;
}
void change(int x, int k) {
int l = l(x), r = r(x);
if (l == r) {
hash(x) = 2;
rhash(x) = 2;
return;
}
int mid = l + r >> 1;
if (k <= mid)
change(x * 2, k);
else
change(x * 2 + 1, k);
pu(x);
}
int qry(int x, int ll, int rr, int op) {
int l = l(x), r = r(x);
if (l >= ll && r <= rr) {
if (op) return hash(x);
return rhash(x);
}
int mid = l + r >> 1, sum = 0;
if (ll <= mid) {
sum = qry(x * 2, ll, rr, op);
if (rr > mid) {
int num = qry(x * 2 + 1, ll, rr, op);
if (op)
sum = (1ll * sum * ms[min(rr, r) - mid] % P + num) % P;
else
sum = (1ll * num * ms[mid - max(l, ll) + 1] % P + sum) % P;
}
} else if (rr > mid) {
sum = qry(x * 2 + 1, ll, rr, op);
}
return sum;
}
void solve() {
cin >> n;
upp(i, 1, n) cin >> a[i];
build(1, 1, n);
bool flag = 1;
upp(i, 1, n) {
if (i > 1 && i < n) {
int len = min(a[i] - 1, n - a[i]);
if (qry(1, a[i] - len, a[i] - 1, 1) !=
qry(1, a[i] + 1, a[i] + len, 0)) {
flag = 0;
break;
}
}
change(1, a[i]);
}
if (flag)
cout << "N" << endl;
else
cout << "Y" << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int tt;
cin >> tt;
while (tt--) {
init();
solve();
}
return 0;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...