权值线段树
其实权值线段树在学习主席树的时候我就提到过这个东西。
权值线段树和普通线段树之间区别就是在于 它存储的是 区间内数的个数
所以用这种数据结构我们可以求解一个 完整区间的第k大 ,要注意和主席树的区别。 主席树更加强大!!
学了主席树反过来学权值线段树超简单
直接上例题:黑匣子https://www.luogu.org/problemnew/show/P1801
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <string.h> 5 #include <vector> 6 #include <map> 7 #include <random> 8 #include <sqlite3.h> 9 10 const int maxn = 3e5 + 10; 11 12 int k; 13 int arr[maxn]; 14 int u[maxn]; 15 16 struct val_segment_tree{ 17 int l,r; 18 int val; 19 }tree[maxn<<2]; 20 21 void build(int nod,int l,int r) { 22 tree[nod].l = l; 23 tree[nod].r = r; 24 if (l == r) 25 return ; 26 int mid = (l + r) >> 1; 27 build(nod<<1,l,mid); 28 build((nod<<1)+1,mid+1,r); 29 } 30 31 void update(int nod,int t) { 32 int l =tree[nod].l,r = tree[nod].r; 33 if (l == r) { 34 tree[nod].val++; 35 return ; 36 } 37 int mid = (l + r) >> 1; 38 if (t <= mid) { 39 update(nod<<1,t); 40 } 41 else 42 update((nod<<1)+1,t); 43 tree[nod].val = tree[nod<<1].val + tree[(nod<<1)+1].val; 44 } 45 //查找整个区间第k大 46 int query(int nod,int t) { 47 int l = tree[nod].l,r = tree[nod].r; 48 if (l == r) 49 return tree[nod].l; 50 if (t <= tree[nod<<1].val) 51 return query(nod<<1,t); 52 else 53 return query((nod<<1)+1,t-tree[nod<<1].val); 54 } 55 56 std::vector<int> v; 57 int getid(int x) { 58 return lower_bound(v.begin(),v.end(),x)-v.begin()+1; 59 } 60 61 62 int main() { 63 int n,m; 64 scanf("%d%d",&m,&n); 65 for (int i=1;i<=m;i++) { 66 scanf("%d",&arr[i]); 67 v.push_back(arr[i]); 68 } 69 for (int i=1;i<=n;i++) { 70 scanf("%d",&u[i]); 71 } 72 std::sort(v.begin(),v.end()); 73 v.erase(std::unique(v.begin(),v.end()),v.end()); 74 int len = v.size(); 75 build(1,1,len); 76 int h = 0; 77 while (n != h ) { 78 h++; 79 for (int i=u[h-1]+1;i<=u[h];i++) { 80 int val = getid(arr[i]); 81 update(1,val); 82 } 83 printf("%d\n",v[query(1,++k)-1]); 84 } 85 86 }