2724: [Violet 6]蒲公英
Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 2507 Solved: 869
[Submit][Status][Discuss]
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
1 2 3 2 1 2
1 5
3 6
1 5
Sample Output
1
2
1
2
1
HINT
数据范围:
n <= 40000, m <= 50000
题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=2724
Solution
经典的分块,众数是不可合并的,所以不能用线段树来维护。。。
这时候就要用分块啦。。。。
一个定理:两个集合的众数一定包含于一个集合和另一个集合的众数中。
然后预处理出第 i 块 到 第 j 块的众数,还有位置 i 到 j 的某种元素的个数。。
之后用分块维护就好了。。。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#include<map>
#define N 40050
#define LL long long
using namespace std;
inline int Read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,Q,e,m,cnt=0,x=0,t=0;
int a[N],b[N],g[N],sum[N],f[250][250],vis[N];
map<int,int>mp;
vector<int> q[N];
void reset(int k){
int mx=0,s=0;
for(int i=1;i<=cnt;i++) sum[i]=0;
for(int i=(k-1)*e+1;i<=n;i++) {
sum[a[i]]++;
if(sum[a[i]]>sum[mx] || (sum[a[i]]==sum[mx]&&b[a[i]]<b[mx])) mx=a[i];
f[k][g[i]]=mx;
}
}
int calc(int h,int c){
int l=0,r=q[c].size()-1,mid;
if(q[c][l]>h) return 0;if(q[c][r]<=h) return q[c].size();
while(l!=r){
mid=(l+r+1)>>1;
if(q[c][mid]<=h) l=mid;
else r=mid-1;
}
return l+1;
}
void solve(int l,int r,int K){
int now;
x=0;t=0;
if(g[l]==g[r]){
for(int i=l;i<=r;i++){
if(vis[a[i]]==K) continue;vis[a[i]]=K;
now=calc(r,a[i])-calc(l-1,a[i]);
if(now>t || (now==t && b[a[i]]<b[x])){x=a[i];t=now;}
}
x=b[x];
printf("%d\n",x);
return;
}
for(int i=l;i<=e*(g[l]);i++) {
if(vis[a[i]]==K) continue;vis[a[i]]=K;
now=calc(r,a[i])-calc(l-1,a[i]);
if(now>t || (now==t && b[a[i]]<b[x])){x=a[i];t=now;}
}
for(int i=(g[r]-1)*e+1;i<=r;i++) {
if(vis[a[i]]==K) continue;vis[a[i]]=K;
now=calc(r,a[i])-calc(l-1,a[i]);
if(now>t || (now==t && b[a[i]]<b[x])){x=a[i];t=now;}
}
if(g[r]-1>=g[l]+1) {
int j=f[g[l]+1][g[r]-1];
now=calc(r,j)-calc(l-1,j);
if(now>t || (now==t && b[j]<b[x])){x=j;t=now;}
}
x=b[x];
printf("%d\n",x);
return;
}
int main(){
char ch;
LL l,r;
n=Read();Q=Read();e=ceil(sqrt(n));
for(int i=1;i<=n;i++) {
a[i]=Read();
if(!mp[a[i]]){
mp[a[i]]=++cnt;
b[cnt]=a[i];
}
a[i]=mp[a[i]];
q[a[i]].push_back(i);
g[i]=(i+e-1)/e;
}
m=g[n];
for(int i=1;i<=m;i++) reset(i);
for(int i=1;i<=Q;i++){
l=(Read()+x-1)%n+1;r=(Read()+x-1)%n+1;
if(l>r) swap(l,r);
solve(l,r,i);
}
return 0;
}
This passage is made by Iscream-2001.