AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3524
【题解】
用主席树直接查找就行了,如果左子树sum[son[x][0]]-sum[son[last][0]]就去左子树找,右子树同理,如果都没有,那就返回0.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
#define FILE "read"
#define MAXN 500010*32
#define up(i,j,n) for(int i=j;i<=n;++i)
#define dn(i,j,n) for(int i=j;i>=n;--i)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
int n,m,cnt,sum[MAXN],root[MAXN],son[MAXN][2];
int newroot(int last){
sum[++cnt]=sum[last]+1;
son[cnt][0]=son[last][0];
son[cnt][1]=son[last][1];
return cnt;
}
void insert(int l,int r,int &root,int last,int x){
root=newroot(last);
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) insert(l,mid,son[root][0],son[last][0],x);
else insert(mid+1,r,son[root][1],son[last][1],x);
}
int ask(int l,int r,int root,int last,int temp){
if(l==r) return l;
int mid=(l+r)>>1;
if(sum[son[root][0]]-sum[son[last][0]]>temp) return ask(l,mid,son[root][0],son[last][0],temp);
else if(sum[son[root][1]]-sum[son[last][1]]>temp) return ask(mid+1,r,son[root][1],son[last][1],temp);
else return 0;
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(); m=read();
up(i,1,n){int x=read(); insert(1,n,root[i],root[i-1],x);}
up(i,1,m){
int x=read(),y=read();
printf("%d\n",ask(1,n,root[y],root[x-1],(y-x+1)>>1));
}
return 0;
}