主席树模板之区间问题

 

 AC_Code

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 #define rep(i,first,last) for(int i=first;i<=last;i++)
 9 #define dep(i,first,last) for(int i=first;i>=last;i--)
10 const int maxn=1e5+6;
11 int n,m,cnt,root[maxn],a[maxn],x,y,k;//root为根节点编号
12 struct node{int l,r,sum;}T[maxn*50];//l:左儿子编号,r:右儿子编号,sum:值域元素个数和,开40~60倍
13 vector<int>v;
14 int getid(int x){ return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
15 void updata(int l,int r,int &x,int y,int pos){
16     T[++cnt]=T[y],T[cnt].sum++,x=cnt;
17     if(l==r) return ;
18     int mid=(l+r)>>1;
19     if( pos>mid ) updata(mid+1,r,T[x].r,T[y].r,pos);
20     else updata(l,mid,T[x].l,T[y].l,pos);
21 }
22 int query(int l,int r,int x,int y,int k){//传的x,y为编号
23     if( l==r )return l;
24     int mid=(l+r)>>1;
25     int sum=T[T[y].l].sum-T[T[x].l].sum;
26     if( sum>=k ) return query(l,mid,T[x].l,T[y].l,k);
27     else return query(mid+1,r,T[x].r,T[y].r,k-sum);
28 }
29 
30 int main()
31 {
32     scanf("%d%d",&n,&m);
33     rep(i,1,n) scanf("%d",&a[i]),v.push_back(a[i]);
34     sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
35     rep(i,1,n) updata(1,n,root[i],root[i-1],getid(a[i]));
36     rep(i,1,m){
37         scanf("%d%d%d",&x,&y,&k);
38         printf("%d
",v[query(1,n,root[x-1],root[y],k)-1]);
39     }
40     return 0;
41 }

 例题二:P3567 [POI2014]KUR-Couriers

AC_Code;

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=5e5+10;
 5 const int mod=1e9+9;
 6 
 7 struct node{
 8     int l,r,v;
 9 }tree[maxn*40];
10 int a[maxn],root[maxn],n,q,m,tot;
11 vector<int>v;
12 int getid(int x){
13     return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
14 }
15 
16 
17 int build(int l,int r){
18     int p=++tot;
19     if( l<r ){
20         int mid=(l+r)>>1;
21         tree[p].l=build(l,mid);
22         tree[p].r=build(mid+1,r);
23     }
24     return p;
25 }
26 
27 int update(int pre, int l,int r,int x){
28     int p=++tot;
29     tree[p].l=tree[pre].l;
30     tree[p].r=tree[pre].r;
31     tree[p].v=tree[pre].v+1;
32     if( l<r ){
33         int mid=(l+r)>>1;
34         if( x<=mid ) tree[p].l=update(tree[pre].l,l,mid,x);
35         else tree[p].r=update(tree[pre].r,mid+1,r,x);
36     }
37     return p;
38 }
39 
40 int query(int pre,int now,int l,int r,int len){
41     if( l>=r ) return l;
42     int l1=tree[tree[now].l].v-tree[tree[pre].l].v;//计算当前区间大于等于l小于等于mid的数字的数量
43     int rl=tree[tree[now].r].v-tree[tree[pre].r].v;//大于mid小于等于r的数字的数量
44     int mid=(l+r)>>1;
45     if( l1>len ) return query(tree[pre].l,tree[now].l,l,mid,len);//如果大于等于l小于等于mid的数字的数量超过一半就往下查询
46     if( rl>len ) return query(tree[pre].r,tree[now].r,mid+1,r,len);//如果大于mid小于等于r的数字的数量超过一半就往下查询
47     return 0;
48 }
49 
50 int main()
51 {
52     scanf("%d%d",&n,&q);
53     for(int i=1;i<=n;i++){
54         scanf("%d",&a[i]);
55         v.push_back(a[i]);
56     }
57     sort(v.begin(),v.end());
58     v.erase(unique(v.begin(),v.end()),v.end());
59     m=v.size();
60     root[0]=build(1,m);
61     for(int i=1;i<=n;i++){
62         int id=getid(a[i]);
63         root[i]=update(root[i-1],1,m,id);
64     }
65     while( q-- ){
66         int a1,a2;
67         scanf("%d%d",&a1,&a2);
68         int f=query(root[a1-1],root[a2],1,m,(a2-a1+1)/2);
69         if( f==0 ) printf("0
");
70         else printf("%d
", v[f-1]);
71     }
72     return 0;
73 }

 

原文地址:https://www.cnblogs.com/wsy107316/p/12343587.html