蒲公英
题目描述
亲爱的哥哥:
你在那个城市里面过得好吗?
我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!
它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤
出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……
最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了
呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!
哥哥你要快点回来哦!
“蒲公英吗……”
在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。
为了简化起见,我们把所有的蒲公英看成一个长度为 n 的序列 (a1,a2,a3,...,an),其中ai为一个正整数,表示第i棵蒲公英的种类编号。
而每次询问一个区间[l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。
注意,你的算法必须是在线的。
你在那个城市里面过得好吗?
我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!
它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤
出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……
最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了
呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!
哥哥你要快点回来哦!
爱你的妹妹 Violet
Azure 读完这封信之后微笑了一下。 “蒲公英吗……”
在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。
为了简化起见,我们把所有的蒲公英看成一个长度为 n 的序列 (a1,a2,a3,...,an),其中ai为一个正整数,表示第i棵蒲公英的种类编号。
而每次询问一个区间[l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。
注意,你的算法必须是在线的。
输入
第一行两个整数n,m,表示有 n 株蒲公英, m 次询问。
接下来一行 n 个空格分隔的整数ai,表示蒲公英的种类
再接下来 m 行每行两个整数l0,r0.我们令上次询问的结果为 x(如果这是第一次询问,则x=0)。
令l=(l0+x-1) mod n+1,r=(r0+x-1) mod n+1,如果l>r,则交换l,r。
最终的询问区间为[l,r]。
接下来一行 n 个空格分隔的整数ai,表示蒲公英的种类
再接下来 m 行每行两个整数l0,r0.我们令上次询问的结果为 x(如果这是第一次询问,则x=0)。
令l=(l0+x-1) mod n+1,r=(r0+x-1) mod n+1,如果l>r,则交换l,r。
最终的询问区间为[l,r]。
输出
输出m行。每行一个整数,表示每次询问的结果。
样例输入
6 3
1 2 3 2 1 2
1 5
3 6
1 5
样例输出
1
2
1
提示
对于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; }