BZOJ2724: [Violet 6]蒲公英

分块
不带修改的,可以先预处理f[i][j]表示第i块到第j块的众数,s[i][j]表示第1到第i块j出现的次数,每加入一个块,新的众数只可能是原块的众数、新块的众数或新块里的一个数,在新块里找一下就可以了,预处理 O(nn)
询问的话,被完全覆盖的块的众数可以 O(1) 知道,然后和求f[i][j]类似,在两端的块内暴力找一下



code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

const int maxnn = 310;
const int maxn = 61000;
struct node
{
    int x,y,i;
}q[maxn]; int dy[maxn],k;
int id[maxn],st[maxnn],n,m,N;
int a[maxn],s[maxnn][maxn],f[maxnn][maxnn];
int ci[maxn],ti[maxn],times;

bool cmp(node x,node y){return x.x<y.x;}
bool cmp2(node x,node y){return x.i<y.i;}

int main()
{
    scanf("%d%d",&n,&m); N=sqrt(n);
    rep(i,1,n)
    {
        id[i]=(i-1)/N+1;
        scanf("%d",&q[i].x);
        q[i].i=i;
    }
    sort(q+1,q+n+1,cmp); k=0; q[0].x=q[1].x-1;
    rep(i,1,n)
    {
        if(q[i].x!=q[i-1].x)k++;
        q[i].y=k; dy[k]=q[i].x;
    }
    sort(q+1,q+n+1,cmp2);
    rep(i,1,n)a[i]=q[i].y;

    rep(i,1,id[n]) st[i]=(i-1)*N+1;
    st[id[n]+1]=n+1;
    rep(i,1,id[n])
    {
        int mx=0;
        rep(j,st[i],st[i+1]-1)
        {
            ci[a[j]]++;
            int s1=ci[a[j]];
            int s2=ci[mx];
            if(s1>s2||(s1==s2&&a[j]<mx))mx=a[j];
        }
        rep(j,1,k)
        {
            s[i][j]=ci[j]+s[i-1][j];
            ci[j]=0;
        }
        f[i][i]=mx;
    }
    rep(i,1,id[n])
    {
        rep(j,i+1,id[n])
        {
            int mx=f[i][j-1];
            int s1=s[j][f[j][j]]-s[i-1][f[j][j]];
            int s2=s[j][mx]-s[i-1][mx];
            if(s1>s2||(s1==s2&&f[j][j]<mx)) mx=f[j][j];
            for(int l=st[j];l<st[j+1];l++)
            {
                int t=a[l];
                s1=s[j][t]-s[i-1][t];
                s2=s[j][mx]-s[i-1][mx];
                if(s1>s2||(s1==s2&&t<mx)) mx=t;
            }
            f[i][j]=mx;
        }
    }

    times=0; int lastans=0;
    while(m--)
    {
        times++;
        int x,y;scanf("%d%d",&x,&y);
        x=(x+lastans-1)%n+1;
        y=(y+lastans-1)%n+1;
        if(x>y)swap(x,y);
        int t1=id[x],t2=id[y];
        if(t1==t2)
        {
            int mx=0;
            rep(i,x,y)
            {
                if(ti[a[i]]!=times)
                {
                    ti[a[i]]=times;
                    ci[a[i]]=0;
                }
                ci[a[i]]++;
                if(ci[a[i]]>ci[mx]||(ci[a[i]]==ci[mx]&&a[i]<mx)) 
                    mx=a[i];
            }
            mx=dy[mx];
            printf("%d\n",mx);
            lastans=mx;
        }
        else
        {
            int mx=f[t1+1][t2-1];
            if(ti[mx]!=times)
            {   
                ti[mx]=times;
                ci[mx]=0;
            }
            rep(i,x,st[t1+1]-1)
            {
                if(ti[a[i]]!=times)
                {
                    ti[a[i]]=times;
                    ci[a[i]]=0;
                }
                ci[a[i]]++;
                int s1=ci[a[i]]+s[t2-1][a[i]]-s[t1][a[i]];
                int s2=ci[mx]+s[t2-1][mx]-s[t1][mx];
                if(s1>s2||(s1==s2&&a[i]<mx)) mx=a[i];
            }
            rep(i,st[t2],y)
            {
                if(ti[a[i]]!=times)
                {
                    ti[a[i]]=times;
                    ci[a[i]]=0;
                }
                ci[a[i]]++;
                int s1=ci[a[i]]+s[t2-1][a[i]]-s[t1][a[i]];
                int s2=ci[mx]+s[t2-1][mx]-s[t1][mx];
                if(s1>s2||(s1==s2&&a[i]<mx)) mx=a[i];
            }
            mx=dy[mx];
            printf("%d\n",mx);
            lastans=mx;
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值