Loading

BZOJ-2724 蒲公英

蒲公英

求区间众数

分块

用的蓝书法二做的:预处理每个区间的最大众数,然后二分检查更新答案,同时更新边角的答案,记得分块的数量的是 \(\sqrt{m * log_{2}n}\)

这个代码过不了 acwing 的:https://www.acwing.com/problem/content/251/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 4e4 + 10;
#define endl '\n'
int num[maxn], a[maxn];
int L[maxn], R[maxn], pos[maxn];
int id[maxn], cnt[maxn];
int h[1010][1010];
vector<int>b[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    // freopen("text.in", "rb", stdin);
    // freopen("text.out", "wb", stdout);
    int n, m;
    cin >> n >> m;
    for(int i=1; i<=n; i++) {cin >> num[i]; a[i] = num[i];}
    sort(a + 1, a + 1 + n);
    int tp = 0, nn = max(1, (int)(n / sqrt(m * log2(n))));
    int t = n / nn;
    a[0] = a[1] - 1;
    for(int i=1; i<=n; i++)
    {
        if(a[i] != a[i-1])
        {
            id[++tp] = a[i];
        }
    }
    for(int i=1; i<=n; i++)
    {
        num[i] = lower_bound(id + 1, id + tp + 1, num[i]) - id;
        b[num[i]].push_back(i);
        // cout << num[i] << " ";
    }
    // cout << endl;

    for(int i=1; i<=t; i++)
    {
        L[i] = R[i-1] + 1;
        R[i] = i * nn;
        // cout << L[i] << " " << R[i] << endl;
    }
    // cout << endl << endl;
    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=0; j<=tp; j++) cnt[j] = 0;
        for(int j=i; j<=t; j++)
        {
            int x = h[i][j-1];
            int y = cnt[x];
            for(int k=L[j]; k<=R[j]; k++)
            {
                cnt[num[k]]++;
                if(cnt[num[k]] > y || (cnt[num[k]] == y && num[k] < x))
                {
                    x = num[k];
                    y = cnt[x];
                }
            }
            h[i][j] = x;
        }
    }

    int ans = 0, way = 0;
    while(m--)
    {
        int x, y;
        cin >> x >> y;
        x = (x + ans - 1) % n + 1;
        y = (y + ans - 1) % n + 1;
        if(x > y) swap(x, y);
        // cout << x << " " << y << endl;
        int tx = pos[x], ty = pos[y];
        ans = way = 0;
        if(tx == ty)
        {
            for(int i=x; i<=y; i++)
            {
                int temp = upper_bound(b[num[i]].begin(), b[num[i]].end(), y) - lower_bound(b[num[i]].begin(), b[num[i]].end(), x);
                if(temp > way || (temp == way && num[i] < ans))
                {
                    ans = num[i];
                    way = temp;
                }
            }
        }
        else
        {
            for(int i=x; i<=R[tx]; i++)
            {
                int temp = upper_bound(b[num[i]].begin(), b[num[i]].end(), y) - lower_bound(b[num[i]].begin(), b[num[i]].end(), x);
                if(temp > way || (temp == way && num[i] < ans))
                {
                    ans = num[i];
                    way = temp;
                }
            }
            for(int i=L[ty]; i<=y; i++)
            {
                int temp = upper_bound(b[num[i]].begin(), b[num[i]].end(), y) - lower_bound(b[num[i]].begin(), b[num[i]].end(), x);
                if(temp > way || (temp == way && num[i] < ans))
                {
                    ans = num[i];
                    way = temp;
                }
            }
            if(tx + 1 <= ty - 1)
            {
                int now = h[tx+1][ty-1];
                int temp = upper_bound(b[now].begin(), b[now].end(), y) - lower_bound(b[now].begin(), b[now].end(), x);
                if(temp > way || (temp == way && now < ans))
                {
                    ans = now;
                    way = temp;
                }
            }
        }
        ans = id[ans];
        cout << ans << endl;
    }
    return 0;
}
posted @ 2022-05-23 20:51  dgsvygd  阅读(24)  评论(0编辑  收藏  举报