主席树 模板题 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 }