数组大小开到一千二百万才过- -
可以把数先离散化再全都加到主席树中。
对于一个区间[from,to]
取中间点mid
看看小于mid的数有多少个,如果个数的两倍<=to-from+1那么左边就不存在我们要找的数。
右面同理。如果大于mid的数<=to-from+1那么右面也不存在我们要找的数。
如果两边都不存在就return 0;
#include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<algorithm> #define mid ((l+r)>>1) using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch==‘-‘) f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-‘0‘; ch=getchar(); } return num*f; } long long rt[12000000]; long long ls[12000000]; long long rs[12000000]; long long sum[12000000]; long long q[1000000]; long long s[1000000]; int tot; void build(long long &o,int l,int r){ o=++tot; sum[o]=0; if(l==r) return; build(ls[o],l,mid); build(rs[o],mid+1,r); } void update(long long &o,int l,int r,long long last,long long p){ o=++tot; ls[o]=ls[last]; rs[o]=rs[last]; sum[o]=sum[last]+1; if(l==r) return; if(p<=mid) update(ls[o],l,mid,ls[last],p); else update(rs[o],mid+1,r,rs[last],p); } int query(int from,int to,int l,int r,int p){ if(l==r) return l; if(2*(sum[ls[to]]-sum[ls[from]])>p) return query(ls[from],ls[to],l,mid,p); if(2*(sum[rs[to]]-sum[rs[from]])>p) return query(rs[from],rs[to],mid+1,r,p); return 0; } int main(){ int n=read(),m=read(); for(int i=1;i<=n;++i) s[i]=q[i]=read(); sort(s+1,s+n+1); int size=unique(s+1,s+n+1)-(s+1); build(rt[0],1,size); for(int i=1;i<=n;++i) q[i]=lower_bound(s+1,s+size+1,q[i])-s; for(int i=1;i<=n;++i) update(rt[i],1,size,rt[i-1],q[i]); for(int i=1;i<=m;++i){ int from=read(),to=read(); printf("%lld\n",s[query(rt[from-1],rt[to],1,size,to-from+1)]); } return 0; }