bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式

这个,要处理各个数的话得先离散,我用的桶。

我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数。

证明:若不是这里的数连区间的众数都达不到。

我已开始把某个离散后的值当成了坐标,调了好久.......

#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
int b[40010],a[40010],n,m,lon,pos[40010],t,p[40010],back[40010],num[40010],f[210][210],sz;
int cmp(const int x,const int y)
{
    if(b[x]<b[y])return 1;
    if(b[x]==b[y]&&x<y)return 1;
    return 0;
}
vector<int> place[40010];
inline void do_it(int x)
{
    memset(num,0,sizeof(num));
    int who=0,how=0;
    for(int i=(x-1)*lon+1;i<=n;i++)
    {
      num[a[i]]++;
      if(num[a[i]]>how||(num[a[i]]==how&&back[a[i]]<back[who]))
        who=a[i],how=num[a[i]];
      f[x][pos[i]]=who;
    }
}
inline void Init()
{
    scanf("%d%d",&n,&m);
    lon=(int)sqrt(n+0.5);
    for(int i=1;i<=n;i++)
    {
      scanf("%d",&b[i]);
      p[i]=i;
      pos[i]=(i-1)/lon+1;
    }
    sort(p+1,p+n+1,cmp);
    for(int i=1;i<=n;i++)
    {
      if(b[p[i]]!=b[p[i-1]])
      {
        a[p[i]]=++sz;
        back[sz]=b[p[i]];
      }
      else
        a[p[i]]=sz;
      place[sz].push_back(p[i]);
    }
    t=pos[n];
    for(int i=1;i<=t;i++)do_it(i);
}
inline int query(int l,int r,int x)
{
    return upper_bound(place[x].begin(),place[x].end(),r)-lower_bound(place[x].begin(),place[x].end(),l);
}
inline int Min(int x,int y){return x<y?x:y;}
inline int work(int l,int r)
{
    int z=pos[l]+1,y=pos[r]-1;
    int who=f[z][y],how=query(l,r,who);
    int zzh=(z-1)*lon;
    zzh=Min(zzh,r);
    for(int i=l;i<=zzh;i++)
    {
      int x=query(l,r,a[i]);
      if(x>how||(x==how&&a[i]<who))
         who=a[i],how=x;
    }
    if(pos[l]!=pos[r])
    {
        zzh=(y*lon)+1;
        for(int i=zzh;i<=r;i++)
        {
          int x=query(l,r,a[i]);
          if(x>how||(x==how&&a[i]<who))
             who=a[i],how=x;
        }
    }
    return back[who];
}
int main()
{
    Init();
    int k=0;
    for(int i=1;i<=m;i++)
    {
       int x,y;
       scanf("%d%d",&x,&y);
       x=(x+k-1)%n+1;
       y=(y+k-1)%n+1;
       if(x>y)x^=y^=x^=y;
       k=work(x,y);
       printf("%d\n",k);
    }
    return 0;
}

 

posted @ 2017-06-14 07:35  TS_Hugh  阅读(370)  评论(0编辑  收藏  举报