主席树 模板题 luogu([POI2014]KUR-Couriers)

求区间内是否有个数大于二分之一的数,有的话输出这个数,没有的话输出0.

在询问的时候,如果左边有sum大于这个limit,就可以继续求,如果右边有sum大于limit  也递归,

如果都不行,返回 0;

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<string.h>
 4 #include<math.h>
 5 using namespace std;
 6 const int maxn=5e5+10;
 7 int Root[maxn],cnt;
 8 struct node
 9 {
10     int ln,rn,sum;
11 }tree[maxn*20];
12 void add(int &x,int y,int l,int r,int num)
13 {
14     tree[++cnt]=tree[y];tree[cnt].sum++;x=cnt;
15     if(l==r) return;
16     int mid=l+r>>1;
17     if(num<=mid) add(tree[x].ln,tree[y].ln,l,mid,num);
18     else add(tree[x].rn,tree[y].rn,mid+1,r,num);
19 }
20 int query(int x,int y,int l,int r,int limit)
21 {
22     if(l==r){
23         if(tree[x].sum-tree[y].sum>=limit) return l;
24         else return 0;
25     }
26     int left1=tree[x].ln,left2=tree[y].ln;
27     int right1=tree[x].rn,right2=tree[y].rn;
28     int mid=l+r>>1;
29     if(tree[left1].sum-tree[left2].sum>=limit){
30         return query(left1,left2,l,mid,limit);
31     }
32     else if(tree[right1].sum-tree[right2].sum>=limit){
33         return query(right1,right2,mid+1,r,limit);
34     }
35     else return 0;
36 }
37 int main()
38 {
39     int n,m;
40     scanf("%d%d",&n,&m);
41     for(int i=1;i<=n;i++){
42         int tmp;
43         scanf("%d",&tmp);
44         add(Root[i],Root[i-1],1,n,tmp);
45     }
46     for(int i=1;i<=m;i++){
47         int l,r;
48         scanf("%d%d",&l,&r);
49         int limit=(r-l+1)/2+1;
50         printf("%d\n",query(Root[r],Root[l-1],1,n,limit));
51     }
52     return 0;
53 }

 

posted @ 2019-10-09 22:16  古比  阅读(692)  评论(0编辑  收藏  举报