亲爱的哥哥:
你在那个城市里面过得好吗?
我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!
它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤
出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……
最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了
呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!
哥哥你要快点回来哦!
爱你的妹妹 Violet
Azure 读完这封信之后微笑了一下。
“蒲公英吗……”
在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。
为了简化起见,我们把所有的蒲公英看成一个长度为 n 的序列 (a1,a2,a3,...,an),其中ai为一个正整数,表示第i棵蒲公英的种类编号。
而每次询问一个区间[l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。
注意,你的算法必须是在线的。
对于20%的数据,保证1≤n,m≤3000。
对于100%的数据,保证1≤n≤40000,1≤m≤50000,1≤ai≤10^9
在线求区间内的众数
分块
pre[i][j]表示在第i块(包括第i块)之前j这个数出现的次数
f[i][j]记录第i块到第j块这段区间内的众数及其出现的次数
(书上给的做法是用一个vector记录每个数在这个序列中出现的位置,然后在vector中lower_bound一下就可以求出出现次数,但是疯狂TLE)
对每次询问a,b
答案要么是bl[a]+1~bl[b]-1这些块的众数,要么是a~bl[a]*blo或者bl[b]-1~b之内的某个数
预处理是n*sqrt(n),询问是sqrt(n)
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
map<int,int>mp;
int n,m,blo,id;
int bl[N],v[N],cnt[N],val[N],pre[205][N];
struct orz{
int val,cnt;}f[205][205];
void does()
{
for (int i=1;i<=bl[n];i++)
{
for (int j=1;j<=id;j++) pre[i][j]=pre[i-1][j];
for (int j=(i-1)*blo+1;j<=i*blo&&j<=n;j++) pre[i][v[j]]++;
}
for (int l=1;l<=bl[n];l++)
for (int r=l;r<=bl[n];r++)
{
f[l][r]=f[l][r-1];
orz now=f[l][r];
for (int i=(r-1)*blo+1;i<=r*blo&&i<=n;i++)
{
if (pre[r][v[i]]-pre[l-1][v[i]]>now.cnt || pre[r][v[i]]-pre[l-1][v[i]]==now.cnt&&val[v[i]]<val[now.val])
{
now.val=v[i];
now.cnt=pre[r][v[i]]-pre[l-1][v[i]];
}
}
f[l][r]=now;
}
}
int ask(int a,int b)
{
orz ans=f[bl[a]+1][bl[b]-1];
for (int i=a;i<=bl[a]*blo&&i<=b;i++)
{
cnt[v[i]]++;
int t=cnt[v[i]]+max(pre[bl[b]-1][v[i]]-pre[bl[a]][v[i]],0);
if (t>ans.cnt||t==ans.cnt&&val[v[i]]<val[ans.val]) ans.val=v[i],ans.cnt=t;
}
if (bl[a]!=bl[b])
{
for (int i=(bl[b]-1)*blo+1;i<=b;i++)
{
cnt[v[i]]++;
int t=cnt[v[i]]+max(pre[bl[b]-1][v[i]]-pre[bl[a]][v[i]],0);
if (t>ans.cnt||t==ans.cnt&&val[v[i]]<val[ans.val]) ans.val=v[i],ans.cnt=t;
}
}
for (int i=a;i<=bl[a]*blo&&i<=b;i++) cnt[v[i]]--;
if (bl[a]!=bl[b])
for (int i=(bl[b]-1)*blo+1;i<=b;i++) cnt[v[i]]--;
return ans.val;
}
int main()
{
scanf("%d%d",&n,&m);
blo=200;
for (int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
if (!mp[v[i]])
{
mp[v[i]]=++id;
val[id]=v[i];
}
v[i]=mp[v[i]];
}
for (int i=1;i<=n;i++) bl[i]=(i-1)/blo+1;
does();
int ans=0,a,b;
for (int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
a=(a+ans-1)%n+1; b=(b+ans-1)%n+1;
if (a>b) swap(a,b);
ans=val[ask(a,b)];
printf("%d\n",ans);
}
return 0;
}
View Code