bzoj2724 [Violet 6]蒲公英 分塊
阿新 • • 發佈:2019-01-28
題意:強制線上,求區間眾數。
說實話還沒有用過除了反演莫隊以外的分塊。。
具體的話就是分成sqrtn塊,然後記錄每一塊的答案和字首。
然後詢問的時候,如果
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=2e5+5 ;
typedef long long ll;
const int mx=305;
int ans[mx][mx],n,m,l,r;
int sum[N][mx],cnt[N];
int a[N],b[N],bel[N];
int main()
{
scanf("%d%d",&n,&m);
int c=floor(sqrt(n))+1;
fo(i,1,n)
{
scanf("%d",&a[i]);
bel[i]=(i-1)/c+1;
b[i]=a[i];
}
sort(b+1,b+1 +n);
l=unique(b+1,b+n+1)-b-1;
fo(i,1,n)
a[i]=lower_bound(b+1,b+l+1,a[i])-b;
fo(i,1,bel[n])
{
int x=0;
fo(j,(i-1)*c+1,n)
{
cnt[a[j]]++;
if(!x||cnt[a[j]]>cnt[x]||cnt[a[j]]==cnt[x]&&a[j]<x)x=a[j];
ans[i][bel[j]]=x;
}
fo(j,(i-1 )*c+1,n)
if (cnt[a[j]])cnt[a[j]]=0;
}
fo(i,1,n)sum[a[i]][bel[i]]++;
fo(i,1,l)
fo(j,1,bel[n])
sum[i][j]+=sum[i][j-1];
int x=0;
while (m--)
{
int u,v;
scanf("%d%d",&u,&v);
u=1ll*(u+x-1)%n+1;
v=1ll*(v+x-1)%n+1;
if (u>v)swap(u,v);
int l=bel[u],r=bel[v];
if (r-l<=1)
{
x=0;
fo(i,u,v)
{
cnt[a[i]]++;
if (!x||cnt[a[i]]>cnt[x]||cnt[a[i]]==cnt[x]&&a[i]<x)x=a[i];
}
fo(i,u,v)if (cnt[a[i]])cnt[a[i]]=0;
x=b[x];
printf("%d\n",x);
continue;
}
x=ans[l+1][r-1];
fo(i,u,l*c)
{
cnt[a[i]]++;
if (!x||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]>cnt[x]+sum[x][r-1]-sum[x][l]||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]==cnt[x]+sum[x][r-1]-sum[x][l]&&a[i]<x) x=a[i];
}
fo(i,(r-1)*c+1,v)
{
cnt[a[i]]++;
if (!x||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]>cnt[x]+sum[x][r-1]-sum[x][l]||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]==cnt[x]+sum[x][r-1]-sum[x][l]&&a[i]<x) x=a[i];
}
fo(i,u,l*c)
if (cnt[a[i]])cnt[a[i]]=0;
fo(i,(r-1)*c+1,v)
if (cnt[a[i]])cnt[a[i]]=0;
x=b[x];
printf("%d\n",x);
}
}