【BZOJ 2821】作诗

【题目链接】

          https://www.lydsy.com/JudgeOnline/problem.php?id=2821  

【算法】

          如果不强制在线,显然莫队是可以解决此题的,那么,强制在线怎么办呢? 分块

          将这个序列分成sqrt(n)段(sqrt表示开方),预处理每段每个数出现的次数与该段“多少数出现了正偶数次”,就可以在线回答询问了

【代码】

             

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const int MAXB = 320;

int i,n,m,c,l,r,x,y,len,block,lastans;
int a[MAXN],belong[MAXN],cnt[MAXN],L[MAXB],R[MAXB];
int sum[MAXB][MAXN],ans[MAXB][MAXB];

inline void init()
{
    int i,j,k;
    len = (int)sqrt(n);
    block = n / len;
    for (i = 1; i <= block; i++)
    {
        L[i] = (i - 1) * len + 1;
        R[i] = i * len;
    }
    if (R[block] < n)
    {
        block++;
        L[block] = R[block-1] + 1;
        R[block] = n;
    }
    for (i = 1; i <= n; i++) belong[i] = (i - 1) / len + 1;
    for (i = 1; i <= n; i++) sum[belong[i]][a[i]]++;
    for (i = 1; i <= block; i++) 
    {
        for (j = 1; j <= c; j++)
        {
            sum[i][j] += sum[i-1][j];
        }
    }
    for (i = 1; i <= block; i++)
    {
        for (j = i; j <= block; j++)
        {    
            ans[i][j] = ans[i][j-1];
            for (k = L[j]; k <= R[j]; k++)
            {
                cnt[a[k]]++;
                if (cnt[a[k]] % 2 == 0) ans[i][j]++;
                else if (cnt[a[k]] > 1) ans[i][j]--;
            }
        }
        for (j = L[i]; j <= n; j++) cnt[a[j]]--;
    }
}
inline int query(int l,int r)
{
    int i,ret = 0,t;
    int p = belong[l],
        q = belong[r];
    if (p == q)
    {
        for (i = l; i <= r; i++)
        {
            cnt[a[i]]++;
            if (cnt[a[i]] % 2 == 0) ret++;
            else if (cnt[a[i]] > 1) ret--;
        }
        for (i = l; i <= r; i++) cnt[a[i]]--;
        return ret;
    } else
    {
        ret = ans[p+1][q-1];
        for (i = l; i <= R[p]; i++)
        {
            cnt[a[i]]++;
            t = sum[q-1][a[i]] - sum[p][a[i]] + cnt[a[i]];
            if (t % 2 == 0) ret++;
            else if (t > 1) ret--;
        }
        for (i = L[q]; i <= r; i++)
        {
            cnt[a[i]]++;
            t = sum[q-1][a[i]] - sum[p][a[i]] + cnt[a[i]];
            if (t % 2 == 0) ret++;
            else if (t > 1) ret--;
        }
        for (i = l; i <= R[p]; i++) cnt[a[i]]--;
        for (i = L[q]; i <= r; i++) cnt[a[i]]--;
        return ret;
    }
}

int main()
{
    
    scanf("%d%d%d",&n,&c,&m);
    for (i = 1; i <= n; i++) scanf("%d",&a[i]);
    init();
    lastans = 0;
    for (i = 1; i <= m; i++)
    {
        scanf("%d%d",&x,&y);
        l = (x + lastans) % n + 1;
        r = (y + lastans) % n + 1;
        if (l > r) swap(l,r);
        printf("%d\n",lastans = query(l,r));
    }

    return 0;
}

 

posted @ 2018-07-16 16:42  evenbao  阅读(134)  评论(0编辑  收藏  举报