[BZOJ 2124] 等差子序列
阿新 • • 發佈:2018-11-27
Description
給一個排列,問是否存在長度是 \(3\) 的等差子序列。
Solution
列舉中間的元素 \(x\),順序掃描這個排列,用 \(01\) 序列表示每個數是否已經訪問過了。比如 \(3\ 1\ 2\),如果訪問到 \(1\),則 \(01\) 序列為 \(1\ 0\ 1\)。那麼對於一箇中間元素,如果它左右兩邊與它差值相同的位置的 \(01\) 狀態不同,即一個被訪問過(在它左邊)一個還未訪問(在它右邊),則可構成等差子序列。線段樹維護正反方向的 \(hash\) 值即可,支援單點修改區間查詢。
Code
#include <cstdio> const int N = 10005; int hs1[N<<2], hs2[N<<2], bin[N], a[N]; int read() { int x = 0; char c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + (c ^ 48); c = getchar(); } return x; } int max(int x, int y) { return x > y ? x : y; } int min(int x, int y) { return x < y ? x : y; } void build(int cur, int l, int r) { if (l == r) { hs1[cur] = hs2[cur] = 1; return; } int mid = l + ((r - l) >> 1); build(cur << 1, l, mid); build(cur << 1 | 1, mid + 1, r); hs1[cur] = hs1[cur<<1] * bin[r-mid] + hs1[cur<<1|1]; hs2[cur] = hs2[cur<<1] + hs2[cur<<1|1] * bin[mid-l+1]; } void update(int cur, int l, int r, int p) { if (l == r) { hs1[cur] = hs2[cur] = 2; return; } int mid = l + ((r - l) >> 1); if (p <= mid) update(cur << 1, l, mid, p); else update(cur << 1 | 1, mid + 1, r, p); hs1[cur] = hs1[cur<<1] * bin[r-mid] + hs1[cur<<1|1]; hs2[cur] = hs2[cur<<1] + hs2[cur<<1|1] * bin[mid-l+1]; } int query(int cur, int l, int r, int L, int R, int f) { if (L <= l && r <= R) return f ? hs1[cur] : hs2[cur]; int mid = l + ((r - l) >> 1), res = 0; if (L <= mid) res = query(cur << 1, l, mid, L, R, f); if (mid < R) { if (f) res = res * bin[min(R,r)-mid] + query(cur << 1 | 1, mid + 1, r, L, R, f); else res = res + query(cur << 1 | 1, mid + 1, r, L, R, f) * (L <= mid ? bin[mid-max(L,l)+1] : 1); } return res; } int main() { int T = read(); bin[0] = 1; for (int i = 1; i <= 10000; ++i) bin[i] = bin[i-1] * 3; while (T--) { int n = read(), ok = 0; build(1, 1, n); for (int i = 1; i <= n; ++i) a[i] = read(); for (int i = 1; i <= n; ++i) { update(1, 1, n, a[i]); if (a[i] == 1 || a[i] == n) continue; if ((a[i] << 1) - 1 <= n) { if (query(1, 1, n, 1, a[i] - 1, 1) != query(1, 1, n, a[i] + 1, a[i] + a[i] - 1, 0)) { ok = 1, puts("Y"); break; } } else { if (query(1, 1, n, a[i] + a[i] - n, a[i] - 1, 1) != query(1, 1, n, a[i] + 1, n, 0)) { ok = 1, puts("Y"); break; } } } if (!ok) puts("N"); } return 0; }