Yuno loves sqrt technology III[Ynoi2019模拟赛]【数组分块】

题目链接


  我们想知道一个区间内的众数的个数,那么,我们可以把区间看成两种形式:「完整区间」、「不完整区间」,我们把一个区间分成这样的两种,然后可以预处理出来一个「完整区间」内的众数的个数,那么如果我们现在假设知道了这个答案,岂不是就可以对不完整区间进行查询了,如果一个不完整区间的数,能改变当前答案,那么也就是说明它的后面的第ans个它自己是在区间内的,那么我们可以预处理这个信息即可。

  当然,本题有个很坑的地方,切记l和r的大小关系一定要判断。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define pii pair
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 5e5 + 7, maxP = 750;
int N, M, p[maxP][maxP], a[maxN], pos_a[maxN], lsan[maxN], _UP, num[maxN] = {0};
vector vt[maxN];
pair t[maxP];
int id, len;
inline int Max(const int &a, const int &b) { return a > b ? a : b; }
inline int Min(const int &a, const int &b) { return a > b ? b : a; }
inline void Init()
{
    id = 0;
    len = (int)sqrt(N + 1);
    int pos = 1, end_pos;
    while(pos <= N)
    {
        id++;
        end_pos = pos + len - 1;
        end_pos = Min(end_pos, N);
        t[id] = MP(pos, end_pos);
        pos = end_pos + 1;
    }
    int maxx;
    for(int i=1; i<=id; i++)
    {
        maxx = 0;
        for(int j=t[i].first; j<=t[i].second; j++)
        {
            num[a[j]]++;
            maxx = Max(maxx, num[a[j]]);
        }
        for(int j=t[i].first; j<=t[i].second; j++)
        {
            num[a[j]] = 0;
        }
        p[i][i] = maxx;
    }
    for(int k=2; k<=id; k++)
    {
        for(int i=1, ql, qr, v; i + k - 1<=id; i++)
        {
            ql = i; qr = i + k - 1;
            maxx = p[ql + 1][qr];
            for(int j=t[i].second, nx_id; j>=t[i].first; j--)
            {
                v = a[j];
                nx_id = pos_a[j] + maxx;
                if(nx_id < vt[v].size() && vt[v][nx_id] <= t[qr].second) maxx++;
            }
            p[ql][qr] = maxx;
        }
    }
}
void read(int &x)
{
    x = 0; char s = getchar();
    while (!isdigit(s)) s = getchar();
    while (isdigit(s)) { x = (x << 1) + (x << 3) + s - '0'; s = getchar(); }
}
int main()
{
    read(N); read(M);
    for(int i=1; i<=N; i++) { read(a[i]); lsan[i] = a[i]; }
    sort(lsan + 1, lsan + N + 1);
    _UP = (int)(unique(lsan + 1, lsan + N + 1) - lsan - 1);
    for(int i=1; i<=N; i++) a[i] = (int)(lower_bound(lsan + 1, lsan + _UP + 1, a[i]) - lsan);
    for(int i=1; i<=N; i++)
    {
        pos_a[i] = (int)vt[a[i]].size();
        vt[a[i]].push_back(i);
    }
    Init();
    for(int i=1, las_ans = 0, l, r, ql, qr, nx_id; i<=M; i++)
    {
        read(l); read(r);
        l ^= las_ans; l = Max(l, 1); l = Min(l, N);
        r ^= las_ans; r = Min(r, N); r = Max(r, 1);
        if(l > r) swap(l, r);
        las_ans = 0;
        ql = (int)(lower_bound(t + 1, t + id + 1, MP(l, 0)) - t);
        qr = (int)(upper_bound(t + 1, t + id + 1, MP(r, INF)) - t - 1);
        while(t[qr].second > r) qr--;
        if(ql <= qr)
        {
            las_ans = p[ql][qr];
            if(l < t[ql].first)
            {
                for(int j=t[ql - 1].second, v; j>=l; j--)
                {
                    v = a[j];
                    nx_id = pos_a[j] + las_ans;
                    if(nx_id < vt[v].size() && vt[v][nx_id] <= r) las_ans++;
                }
            }
            if(r > t[qr].second)
            {
                for(int j=t[qr + 1].first, v; j<=r; j++)
                {
                    v = a[j];
                    nx_id = pos_a[j] - las_ans;
                    if(nx_id >= 0 && vt[v][nx_id] >= l) las_ans++;
                }
            }
        }
        else
        {
            for(int j=l; j<=r; j++)
            {
                num[a[j]]++;
                las_ans = Max(las_ans, num[a[j]]);
            }
            for(int j=l; j<=r; j++)
            {
                num[a[j]] = 0;
            }
        }
        printf("%d\n", las_ans);
    }
    return 0;
}

 

你可能感兴趣的:(分块,分块)