蓝书来的,刚学分块求助

P4168 [Violet] 蒲公英

danefishhh @ 2019-10-21 15:04:09

注释很清楚了..4WA 16TLE 调吐了..大佬帮忙看看

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int n, m, t, sum;
int a[40010], b[40010], pos[40010], L[40010], R[40010], s[210][40010], f[210][210];
vector <int > v[40010];//v[i]记录i出现的位置
void pre() {
    for(int i = 1; i <= t; i ++) {
        L[i] = (i - 1) * t + 1;
        R[i] = i * t;
    }
    if(R[t] < n) t ++, L[t] = R[t - 1] + 1, R[t] = n;
    for(int i = 1; i <= t; i ++) {
        for(int j = L[i]; j <= R[i]; j ++) {
            pos[j] = i;
        }
    }
    for(int i = 1; i <= t; i ++) {
        for(int j = L[i]; j <= R[i]; j ++) {
            s[i][a[j]] ++;
        }
        for(int j = 1; j <= sum; j ++) {
            s[i][j] += s[i - 1][j];
        }
    }//s[i][j]前缀和 : 前i块j出现的次数
    for(int i = 1; i <= t; i ++) {
        for(int j = i; j <= t; j ++) {
            int id = f[i][j - 1];
            int maxn = 0;
            for(int k = L[j]; k <= R[j]; k ++) {
                if(s[j][a[k]] - s[i - 1][a[k]] == maxn) {
                    if(a[k] < id) id = a[k];
                }
                if(s[j][a[k]] - s[i - 1][a[k]] > maxn) {
                    id = a[k];
                    maxn = s[j][a[k]] - s[i - 1][a[k]];
                }
            }
            f[i][j] = id;
        }
    }//块 i ~ j 众数 f[i][j]
}
int query(int l, int r) {
    int p = pos[l], q = pos[r];
    int maxn = 0, id = 0;
    if(p == q) {//暴力
        for(int i = l; i <= r; i ++) {
            int ll = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();//大于等于l的a[i]最先出现的位置
            int rr = upper_bound(v[a[i]].begin(), v[a[i]].end(), r) - v[a[i]].begin() - 1;//小于等于r的a[i]最后出现的位置
            if((rr - ll + 1) > maxn) {
                maxn = rr - ll + 1;
                id = a[i];
            } else if((rr - ll + 1) == maxn) {
                id = min(id, a[i]);
            }
        }
    } else {
        for(int i = l; i <= R[p]; i ++) {
            int ll = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
            int rr = upper_bound(v[a[i]].begin(), v[a[i]].end(), r) - v[a[i]].begin() - 1;
            if((rr - ll + 1) > maxn) {
                maxn = rr - ll + 1;
                id = a[i];
            } else if((rr - ll + 1) == maxn) {
                id = min(id, a[i]);
            }
        }
        for(int i = L[q]; i <= r; i ++) {
            int ll = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
            int rr = upper_bound(v[a[i]].begin(), v[a[i]].end(), r) - v[a[i]].begin() - 1;
            if((rr - ll + 1) > maxn) {
                maxn = rr - ll + 1;
                id = a[i];
            } else if((rr - ll + 1) == maxn) {
                id = min(id, a[i]);
            }
        }
        if(p + 1 <= q - 1) {//整块的
            if(s[q - 1][f[p + 1][q - 1]] - s[p][f[p + 1][q - 1]] > maxn) {
                id = f[p + 1][q - 1];
                maxn = s[q - 1][f[p + 1][q - 1]] - s[p][f[p + 1][q - 1]];
            } else if(s[q - 1][f[p + 1][q - 1]] - s[p][f[p + 1][q - 1]] == maxn) {
                id = min(id, f[p + 1][q - 1]);
            }
        }
    }
    return id;
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) {
        scanf("%d", &a[i]);
        b[i] = a[i];
    }
    std::sort(b + 1, b + n + 1);
    sum = std::unique(b + 1, b + n + 1) - b - 1;//sum为种类数 
    for(int i = 1; i <= n; i ++) {
        a[i] = lower_bound(b + 1, b + sum + 1, a[i]) - b;
        v[a[i]].push_back(i);
    }
    for(int i = 1; i <= sum; i ++) v[i].push_back(INF);//加一个最大值方便二分
    for(int i = 1; i <= sum; i ++) sort(v[i].begin(), v[i].end());
    t = sqrt(n);
    pre();
    int x = 0;
    for(int i = 1; i <= m; i ++) {
        int l, r;
        scanf("%d%d", &l, &r);
        l = (l + x - 1) % n + 1, r = (r + x - 1) % n + 1;
        if(l > r) swap(l, r);
        printf("%d\n", x = query(l, r));
    }
    return 0;
}

by danefishhh @ 2019-10-21 15:07:04

那个 vector 的排序是没用的..它们本来就是有序的


|