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;
}
posted @ 2019-11-13 19:07  dreagonm  阅读(122)  评论(0编辑  收藏  举报