BZOJ 3524 [Poi2014]Couriers 主席树
https://darkbzoj.cf/problem/3524
给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
主席树查找裸题,维护出现次数
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define LL long long 8 const int maxn=500010; 9 int n,m; 10 int rt[maxn]={}; 11 int lc[maxn*20]={},rc[maxn*20]={},siz[maxn*20]={},tot=0; 12 void build(int &x,int y,int l,int r,int z){ 13 x=++tot;siz[x]=siz[y]+1; 14 if(l==r)return; 15 lc[x]=lc[y];rc[x]=rc[y]; 16 int mid=(l+r)/2; 17 if(z<=mid)build(lc[x],lc[y],l,mid,z); 18 else build(rc[x],rc[y],mid+1,r,z); 19 } 20 int getans(int x,int y,int l,int r,int temp){ 21 if(l==r)return l; 22 int mid=(l+r)/2; 23 if(siz[lc[y]]-siz[lc[x]]>temp) return getans(lc[x],lc[y],l,mid,temp); 24 else if(siz[rc[y]]-siz[rc[x]]>temp) return getans(rc[x],rc[y],mid+1,r,temp); 25 else return 0; 26 } 27 int main(){ 28 int x,y,temp; 29 scanf("%d%d",&n,&m); 30 for(int i=1;i<=n;i++){ 31 scanf("%d",&x);rt[i]=rt[i-1]; 32 build(rt[i],rt[i],1,n,x); 33 } 34 for(int i=1;i<=m;i++){ 35 scanf("%d%d",&x,&y);temp=(y-x+1)/2; 36 printf("%d\n",siz[rt[y]]-siz[rt[x-1]]<=temp?0:getans(rt[x-1],rt[y],1,n,temp)); 37 } 38 return 0; 39 }