题目
Waterfall
假如一个数在区间出现的次数大于一半,第(r-l+3)/2小的一定是这个数,然后只要检测这个数出现的次数是否>一半即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5e5+5;
struct tree{int l,r,sum;}t[N*100];
int refl[N],a[N],tot;
int root[N],sz,ans;
void update(int l,int r,int &x,int y,int n)
{
t[++sz]=t[y],t[sz].sum++,x=sz;
if(l==r)
return;
int mid=(l+r)>>1;
if(n<=mid)
update(l,mid,t[x].l,t[y].l,n);
else
update(mid+1,r,t[x].r,t[y].r,n);
}
int query(int l,int r,int x,int y,int k)
{
if(l==r)
{
ans=t[y].sum-t[x].sum;//第k小这个数在询问区间内出现的次数 看其是否>=(r-l+1);
return l;
}
int mid=(l+r)>>1;
int left=t[t[y].l].sum-t[t[x].l].sum;
if(k<=left)
return query(l,mid,t[x].l,t[y].l,k);
return query(mid+1,r,t[x].r,t[y].r,k-left);
}
int main()
{
sz=0;
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),refl[i]=a[i];
sort(refl+1,refl+n+1);
tot=unique(refl+1,refl+n+1)-(refl+1);
for(int i=1;i<=n;i++)
{
int dex=lower_bound(refl+1,refl+tot+1,a[i])-refl;
update(1,tot,root[i],root[i-1],dex);
}
while(m--)
{
int l,r;scanf("%d%d",&l,&r);
int fin=refl[query(1,tot,root[l-1],root[r],(r-l+3)/2)];
if(ans<=(r-l+1)/2)
printf("0\n");
else
printf("%d\n",fin);
}
}