BZOJ2223/3524:[POI2014] Couriers(主席树)
Description
给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
Input
第一行两个数n,m。
第二行n个数,a[i]。
接下来m行,每行两个数l,r,表示询问[l,r]这个区间。
Output
m行,每行对应一个答案。
Sample Input
7 5
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6
Sample Output
1
0
3
0
4
0
3
0
4
HINT
【数据范围】
n,m≤500000
Solution
就是递归查询区间sum是否大于(r-l+1)/2,是的话就递归左右儿子,否则return
如果能一直递归到l==r就是有解,否则无解
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define N (300000+100) 6 using namespace std; 7 struct node{int lson,rson,sum;}Segt[N*40]; 8 int a[N],b[N],n,m,Root[N],Segt_cnt,x,y,lim; 9 10 int Build(int l,int r) 11 { 12 int node=++Segt_cnt; 13 if (l==r) return node; 14 int mid=(l+r)>>1; 15 Segt[node].lson=Build(l,mid); 16 Segt[node].rson=Build(mid+1,r); 17 return node; 18 } 19 20 int Update(int pre,int l,int r,int x) 21 { 22 int node=++Segt_cnt; 23 Segt[node].sum=Segt[pre].sum+1; 24 Segt[node].lson=Segt[pre].lson; 25 Segt[node].rson=Segt[pre].rson; 26 if (l==r) return node; 27 int mid=(l+r)>>1; 28 if (x<=mid) Segt[node].lson=Update(Segt[node].lson,l,mid,x); 29 else Segt[node].rson=Update(Segt[node].rson,mid+1,r,x); 30 return node; 31 } 32 33 int Query(int u,int v,int l,int r) 34 { 35 int mid=(l+r)>>1,c=Segt[v].sum-Segt[u].sum; 36 if (c<=(y-x+1)>>1) return 0; 37 if (l==r) return b[l]; 38 return max(Query(Segt[u].lson,Segt[v].lson,l,mid),Query(Segt[u].rson,Segt[v].rson,mid+1,r)); 39 } 40 41 int main() 42 { 43 scanf("%d%d",&n,&lim); 44 for (int i=1;i<=n;++i) 45 scanf("%d",&a[i]),b[i]=a[i]; 46 sort(b+1,b+n+1); 47 int num=unique(b+1,b+n+1)-b-1; 48 Root[0]=Build(1,num); 49 for (int i=1;i<=n;++i) 50 { 51 int t=lower_bound(b+1,b+num+1,a[i])-b; 52 Root[i]=Update(Root[i-1],1,num,t); 53 } 54 scanf("%d",&m); 55 for (int i=1;i<=m;++i) 56 { 57 scanf("%d%d",&x,&y); 58 int ans=Query(Root[x-1],Root[y],1,num); 59 if (ans) printf("yes %d\n",ans); 60 else printf("no\n"); 61 } 62 }