P2757 [国家集训队]等差子序列
P2757 国家集训队 等差子序列
考虑有用值域
对于 \(1 \le val_i \le \lceil \frac{N}{2} \rceil\) 那么有用值域是 \([1, 2*val_i]\)
对于 \(\lceil \frac{N}{2} \rceil \lt val_i \le N\) 那么有用值域是 \([2*val_i-N, N]\)
然后我们可以发现,对于一对可行解 \(a + c = 2 * val_i (a \lt val_i \lt c)\)
记录 \(l_i\) 为 \(val_i\) 在有用值域内的前缀和, \(r_i\) 为 \(val_i\) 在有用值域内的后缀和。
那么当所有可行 \(a, c\) 在 \(val_i\) 的同一侧的时候 \(l_i\) 和 \(r_i\) 为 \(2*val_i\) 的倍数。
那么有解只要任意一个 \(val_i\), \(l_i, r_i\) 不为0,\(l_i \not\equiv 0 (\mod (2*val_i))\) 并且 \(r_i \not\equiv 0 (\mod (2*val_i))\)
/*
Name:P2757
Copyright: No
Author: Gensokyo_Alice
Date: 26/9/20/ 09:24
Description:
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6+10;
ll N, T, val[MAXN], C[MAXN], l[MAXN], r[MAXN];
void add(ll, ll);
ll ask(ll);
int main() {
ios::sync_with_stdio(false);
#ifdef ZZCAKIOI
#endif
cin >> T;
while (T--) {
cin >> N;
for (ll i = 1; i <= N; i++) {
cin >> val[i];
if (val[i] * 2 - 1 > N) l[i] = ask(N) - ask(val[i]*2-N-1);
else l[i] = ask(2*val[i]-1);
add(val[i], val[i]);
}
for (ll i = 1; i <= N; i++) C[i] = 0;
for (ll i = N; i >= 1; i--) {
if (val[i] * 2 - 1 > N) r[i] = ask(N) - ask(val[i]*2-N-1);
else r[i] = ask(2*val[i]-1);
add(val[i], val[i]);
}
ll flag = 0;
for (ll i = 1; i <= N; i++) {
if (l[i] && r[i] && (r[i] % (2 * val[i]) && l[i] % (2 * val[i]))) {
flag = 1;
}
}
if (flag) puts("Y");
else puts("N");
}
return 0;
}
void add(ll x, ll val) {
while (x <= N) {
C[x] += val;
x += (x & (-x));
}
}
ll ask(ll x) {
ll ret = 0;
while (x) {
ret += C[x];
x -= (x & (-x));
}
return ret;
}
希望我们都有一个光明的未来