您的位置:首页 > 其它

【BZOJ2724】[Violet 6]蒲公英 分块+二分

2017-06-23 18:44 501 查看

【BZOJ2724】[Violet 6]蒲公英

Description



Input



修正一下

l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

Output



Sample Input

6 3

1 2 3 2 1 2

1 5

3 6

1 5

Sample Output

1

2

1

HINT



修正下:

n <= 40000, m <= 50000

题解:分块还是练脑子啊~

结论:一个区间的众数要么是区间中一个块的众数,要么是块外的任意一个数。

这就告诉我们需要预处理出任意两个块之间的所有数的众数,这个可以用离散化+桶+扫一遍实现。

那么对于询问[l,r]我们假设其中最大的连续的块是[ll,rr],那么我们已知了[ll,rr]中的众数,如何判断[l,ll),(rr,r]中的数是不是众数呢?

既然已经将所有数离散化了,我们就可以考虑记录每个数出现的位置。我们将每个数出现的位置从左到右用vector存起来,然后查询的时候二分一下,就知道了这个数在[l,r]中出现了多少次,用它来更新答案就行了。

sqrt(n/logn)大法好~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=40010;
int n,m,nm,B,mx,ans;
int v[maxn],st[maxn],ref[maxn];
int s[810][810];
vector<int> pos[maxn];
struct node
{
int org,val;
}num[maxn];
bool cmp(node a,node b)
{
return a.val<b.val;
}
int rd()
{
int ret=0,f=1;	char gc=getchar();
while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void query(int a,int b,int x)
{
if(!x||st[x])	return ;
int l=0,r=pos[x].size()-1,mid,c,d;
while(l<r)
{
mid=l+r>>1;
if(pos[x][mid]>=a)	r=mid;
else	l=mid+1;
}
c=r;
l=0,r=pos[x].size();
while(l<r)
{
mid=l+r>>1;
if(pos[x][mid]<=b)	l=mid+1;
else	r=mid;
}
d=l-1,st[x]=d-c+1;
if(st[x]>st[mx]||(st[x]==st[mx]&&x<mx))	mx=x;
}
int main()
{
//freopen("bz2724.in","r",stdin);
n=rd(),m=rd();
int i,j,a,b,c,d;
for(i=0;i<n;i++)	num[i].val=rd(),num[i].org=i;
sort(num,num+n,cmp);
for(i=0;i<n;i++)
{
if(!i||num[i].val>num[i-1].val)	ref[++nm]=num[i].val;
v[num[i].org]=nm;
}
B=int(sqrt(double(n)/log(n)));
for(i=0;i<n;i++)	pos[v[i]].push_back(i);
for(i=0;i*B<n;i++)
{
memset(st,0,sizeof(st));
for(mx=0,j=i*B;j<n;j++)
{
st[v[j]]++;
if(st[v[j]]>st[mx]||(st[v[j]]==st[mx]&&v[j]<mx))	mx=v[j];
s[i][j/B]=mx;
}
}
memset(st,0,sizeof(st));
for(i=1;i<=m;i++)
{
a=(rd()+ans-1+n)%n,b=(rd()+ans-1+n)%n;
if(a>b)	swap(a,b);
c=a/B,d=b/B;
if(c==d)
{
for(mx=0,j=a;j<=b;j++)
{
st[v[j]]++;
if(st[v[j]]>st[mx]||(st[v[j]]==st[mx]&&v[j]<mx))	mx=v[j];
}
ans=ref[mx],printf("%d\n",ans);
for(j=a;j<=b;j++)	st[v[j]]--;
continue;
}
mx=0,query(a,b,s[c+1][d-1]);
for(j=a;j<c*B+B;j++)	query(a,b,v[j]);
for(j=d*B;j<=b;j++)	query(a,b,v[j]);
ans=ref[mx],printf("%d\n",ans);
st[s[c+1][d-1]]=0;
for(j=a;j<c*B+B;j++)	st[v[j]]=0;
for(j=d*B;j<=b;j++)	st[v[j]]=0;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: