luogu P3567 [POI2014]KUR-Couriers |莫队+随机化
给一个数列,每次询问一个区间内有没有一个数出现次数超过一半
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5e5+10;
inline int read(){
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x;
}
int A[N],sum[N],cnt[N],belong[N],op;
inline void add(int x){
cnt[A[x]]++;
sum[cnt[A[x]]]++;
if(cnt[A[x]]>op)op=cnt[A[x]];
}
inline void del(int x){
sum[cnt[A[x]]]--;
if(sum[cnt[A[x]]]==0&&op==cnt[A[x]])op--;
cnt[A[x]]--;
}
struct node{
int l,r,id;
}e[N];
inline bool cmp(node t1,node t2){
return (belong[t1.l]^belong[t2.l])? t1.l<t2.l :((belong[t1.l]&1)?t1.r<t2.r:t1.r>t2.r);
}
int n,m,ans[N];
inline int find(int l,int r){
int x=l;
while(cnt[A[x]]!=op)x=rand()%(r-l+1)+l;
return A[x];
}
int main(){
srand(20030302);
n=read(),m=read();
int size=pow(n,1.0/2.0);
int num=ceil((double)n/size);
for(int i=1;i<=num;i++)
for(int j=(i-1)*size+1;j<=i*size;j++)
belong[j]=i;
for(int i=1;i<=n;i++)A[i]=read();
for(int i=1;i<=m;i++)e[i].l=read(),e[i].r=read(),e[i].id=i;
sort(e+1,e+1+m,cmp);
int l=e[1].l,r=e[1].r;
for(int i=l;i<=r;i++)add(i);
for(int i=1;i<=m;i++){
while(l<e[i].l)del(l++);
while(l>e[i].l)add(--l);
while(r<e[i].r)add(++r);
while(r>e[i].r)del(r--);
if((op<<1)>r-l+1)ans[e[i].id]=find(l,r);
else ans[e[i].id]=0;
}
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}
不以物喜,不以己悲