[BZOJ 2124] 等差子序列

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

猜你喜欢

转载自www.cnblogs.com/fly-in-milkyway/p/10028363.html