码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ [P2124] 等差子序列

时间:2018-02-18 15:58:45      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:处理   pac   ret   shu   const   printf   getchar   while   int   

线段树维护哈希值

要求出现长度大于三的等差子序列,我们只要找到长度等于三的就可以了
初看本题没有思路,只能暴力枚举,O(n^4)
后来发现,这个序列是n的一个排列,那么每个数字都只会出现一次
我们可以维护一个 \(01\) 序列 B ,表示某个数字是否出现过,
然后我们从左往右枚举等差中项x并将该项在B中置为1,存在等差数列当且仅当,
B序列以x为中心的极大子区间不是回文子区间
我们该如何高效的判断回文子区间呢,首先维护B的正反两个序列
然后有两种做法
1.线段树维护 \(01\) 序列的哈希值,要注意预处理,以及具体在某步中移多少位
2.用bitset维护

线段树维护哈希值,64位自然溢出

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#define lson l, mid, rt<<1
#define rson mid + 1, r, rt<<1|1
#define ll unsigned long long 
using namespace std;
const int MAXN = 10005, base = 233;
int init() {
    int rv = 0, fh = 1;
    char c = getchar ();
    while(c < '0' || c > '9') {
        if(c == '-') fh = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        rv = (rv<<1) + (rv<<3) + c - '0';
        c = getchar();
    }
    return fh * rv;
}
int T, n;
ll hash1[MAXN<<2], hash2[MAXN<<2], idx[MAXN<<2];
ll Query1(int L, int R, int l, int r,int rt) {
    if(L > R) return 0;
    if(L <= l && r <= R) {
        return hash1[rt];
    }
    int mid = (l + r) >>1;
    ll ans = 0;
    if(L <= mid) ans = Query1(L, R, lson);
    if(mid < R) {
        ans *= idx[min(R, r) - mid]; //注意min(R,r)
        ans += Query1(L, R, rson);
    }
    return ans;
}
ll Query2(int L, int R, int l, int r, int rt) {
    if(L > R) return 0;
    if(L <= l && r <= R) {
        return hash2[rt];
    }
    int mid = (l + r) >>1;
    ll ans = 0;
    if(mid < R) ans = Query2(L ,R, rson);
    if(L <= mid){
        ans *= idx[mid - max(L, l) + 1];
        ans += Query2(L, R, lson);
    }
    return ans;
}
void PushUp(int rt, int m) {
    hash1[rt] = hash1[rt<<1] * idx[m>>1] + hash1[rt<<1|1];
    hash2[rt] = hash2[rt<<1|1] * idx[m - (m>>1)] + hash2[rt<<1];
}
void Update(int x, int l, int r, int rt) {
    if(l >= r) {
        hash1[rt] = hash2[rt] = 1;
        return;
    }
    int mid = (l + r) >>1;
    if(x <= mid) Update(x, lson);
    else Update(x, rson);
    PushUp(rt, r - l + 1);
}
int main() {
    freopen("in.txt", "r", stdin);
    T = init();
    idx[0] = 1;
    for(int i = 1 ; i <= MAXN ; i++) {
        idx[i] = idx[i-1] * base;
    }
    while(T--) {
        n = init();
        memset(hash1, 0, sizeof(hash1));
        memset(hash2, 0, sizeof(hash2));
        bool f = 0;
        for(int i = 1 ; i <= n ; i++) {
            int x = init();
            int len = min(x - 1, n - x);
            if((!f) && (Query1(x - len, x - 1, 1, n, 1) != Query2(x + 1, x + len, 1, n, 1))) {
                f = 1;
            }
            Update(x, 1, n, 1);
        }
        printf("%c\n", f?'Y':'N');
    }
    fclose(stdin);
    return 0;
}

BZOJ [P2124] 等差子序列

标签:处理   pac   ret   shu   const   printf   getchar   while   int   

原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8452817.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!