zoukankan      html  css  js  c++  java
  • BZOJ2724 [Violet]蒲公英(分块)

    区间众数。分块,预处理任意两块间所有数的众数,和每块中所有数的出现次数的前缀和。查询时对不是整块的部分暴力,显然只有这里出现的数可能更新答案。于是可以优美地做到O(n√n)。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 50010
    #define BLOCK 250
    int n,m,a[N],b[N],lastans=0;
    int block,tot,L[N],R[N],pos[N];
    int cnt[N],f[BLOCK][BLOCK],sum[BLOCK][N];
    int main()
    {
        freopen("bzoj2724.in","r",stdin);
        freopen("bzoj2724.out","w",stdout);
        n=read(),m=read();
        for (int i=1;i<=n;i++) b[i]=a[i]=read();
        sort(b+1,b+n+1);
        int t=unique(b+1,b+n+1)-b;
        for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+t,a[i])-b;
        block=sqrt(n);tot=n/block+(n%block>0);
        for (int i=1;i<=n/block;i++)
        L[i]=(i-1)*block+1,R[i]=(i-1)*block+block;
        if (n/block<tot) L[tot]=n/block*block+1,R[tot]=n;
        for (int i=1;i<=tot;i++)
        {
            memset(cnt,0,sizeof(cnt));
            int num=0;
            for (int j=i;j<=tot;j++)
            {
                for (int k=L[j];k<=R[j];k++)
                {
                    cnt[a[k]]++;
                    if (cnt[a[k]]>cnt[num]||cnt[a[k]]==cnt[num]&&a[k]<num) num=a[k];
                }
                f[i][j]=num;
            }
            memcpy(sum[i],sum[i-1],sizeof(sum[i]));
            for (int j=L[i];j<=R[i];j++)
            pos[j]=i,sum[i][a[j]]++;
        }
        memset(cnt,0,sizeof(cnt));
        while (m--)
        {
            int x=read(),y=read();
            x=(x+lastans-1)%n+1,y=(y+lastans-1)%n+1;
            if (x>y) swap(x,y);
            int num=0;
            if (pos[x]==pos[y])
            {
                for (int i=x;i<=y;i++)
                {
                    cnt[a[i]]++;
                    if (cnt[a[i]]>cnt[num]||cnt[a[i]]==cnt[num]&&a[i]<num) num=a[i];
                }
                for (int i=x;i<=y;i++) cnt[a[i]]--;
            }
            else
            {
                num=f[pos[x]+1][pos[y]-1];
                for (int i=x;i<=R[pos[x]];i++)
                {
                    cnt[a[i]]++;
                    if (cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]>cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num]
                    ||cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]==cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num]&&a[i]<num)
                    num=a[i];
                }
                for (int i=L[pos[y]];i<=y;i++)
                {
                    cnt[a[i]]++;
                    if (cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]>cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num]
                    ||cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]==cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num]&&a[i]<num)
                    num=a[i];
                }
                for (int i=x;i<=R[pos[x]];i++) cnt[a[i]]--;
                for (int i=L[pos[y]];i<=y;i++) cnt[a[i]]--;
            }
            lastans=b[num];
            printf("%d
    ",b[num]);
        }
        fclose(stdin);fclose(stdout);
        return 0;
    }
  • 相关阅读:
    CWinApp类 功能
    CreateCompatibleBitmap
    CreateCompatibleDC CreateCompatibleBitmap SelectObject详解
    Linux学习_菜鸟教程_4
    Linux学习_菜鸟教程_1
    Linux学习_菜鸟教程_2
    Linux学习_菜鸟教程_3
    MATLAB生成正弦波
    03补件处理流程
    对数据库中所有的表进行操作
  • 原文地址:https://www.cnblogs.com/Gloid/p/9387795.html
Copyright © 2011-2022 走看看