P3567 [POI2014]KUR-Couriers
简单的主席树上二分。。。
出现次数超过区间长度一半的数肯定在左右子树中sz更大的那个中
向sz更大的子树上跳,如果节点总数就小于区间长度的一半则无解
因为没说ai取值范围所以离散化一下
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int root[500500];
struct Node{
int lson,rson,sz;
}Seg[500500*30];
int n,m,Nodecnt=0;
void insert(int l,int r,int &o,int v){
int p=++Nodecnt;
Seg[p]=Seg[o];
Seg[p].sz++;
o=p;
if(l==r)
return;
int mid=(l+r)>>1;
if(v<=mid)
insert(l,mid,Seg[o].lson,v);
else
insert(mid+1,r,Seg[o].rson,v);
}
int solve(int L,int R,int l,int r,int lo,int ro){
if(Seg[ro].sz-Seg[lo].sz<=((R-L+1)>>1))
return -1;
if(l==r&&(Seg[ro].sz-Seg[lo].sz)>((R-L+1)>>1))
return l;
int mid=(l+r)>>1;
if(Seg[Seg[ro].rson].sz-Seg[Seg[lo].rson].sz>Seg[Seg[ro].lson].sz-Seg[Seg[lo].lson].sz)
return solve(L,R,mid+1,r,Seg[lo].rson,Seg[ro].rson);
else
return solve(L,R,l,mid,Seg[lo].lson,Seg[ro].lson);
}
int a[500500],b[500500],len;
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
len=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+len+1,a[i])-b;
}
for(int i=1;i<=n;i++){
root[i]=root[i-1];
insert(1,len,root[i],a[i]);
}
for(int i=1;i<=m;i++){
int l,r;
scanf("%d %d",&l,&r);
int rev=solve(l,r,1,len,root[l-1],root[r]);
if(rev==-1){
printf("%d\n",0);
}
else{
printf("%d\n",b[rev]);
}
}
return 0;
}