Couriers
POI2014
一眼题,但是被卡内存了
题意
求在[l,r]中出现的次数大于(r-l+1)/2 的数
解
1.一个区间中只会有一个数,因为他出现的次数大于区间的一半
2.如果存在,那么区间第(r-l+1)/2+1大的值,那么答案必然是他
3.只要确认区间第(r-l+1)/2+1大的值的个数是否>(r-l+1)/2即可
4.经典模型:主席树求区间第K值
5.但是此题比较卡内存,如果你有build函数,并且过不了的话,你只要删掉这个函数(不调用),然后恭喜你AC了
具体代码
#include<cstdio>
const int M=500005,N=10600000;
int n,m;
int root[M],sum[N],Ls[N],Rs[N],tot;
void update(int &rt,int pt,int x,int L,int R) {
rt=++tot;
sum[rt]=sum[pt]+1;
Ls[rt]=Ls[pt],Rs[rt]=Rs[pt];
if(L==R)return;
int mid=L+R>>1;
if(x<=mid)update(Ls[rt],Ls[pt],x,L,mid);
else update(Rs[rt],Rs[pt],x,mid+1,R);
}
int query(int rt,int pt,int lim,int K,int L,int R){
if(L==R){
if(sum[rt]-sum[pt]>=lim)return L;
else return 0;
}
int mid=L+R>>1;
if(sum[Ls[rt]]-sum[Ls[pt]]>=K)return query(Ls[rt],Ls[pt],lim,K,L,mid);
else return query(Rs[rt],Rs[pt],lim,K-sum[Ls[rt]]+sum[Ls[pt]],mid+1,R);
}
int main() {
int x;
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%d",&x);
update(root[i],root[i-1],x,1,n);
}
int l,r;
for(int i=1; i<=m; i++) {
scanf("%d %d",&l,&r);
printf("%d\n",query(root[r],root[l-1],(r-l+1)/2+1,(r-l+1)/2+1,1,n));
}
return 0;
}