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 }
View Code

 

 

 

posted @ 2018-04-11 16:38  鲸头鹳  阅读(105)  评论(0编辑  收藏  举报