problem

【代码源 Div1 - 108】#464. 数数(主席树,区间比k小的数的个数)HDU4417_主席树

solution

  • 主席树查询区间比k小的数的个数
  • 建树之后直接在目标区间的主席树内将 H 作为挡板递归计数。
#include<bits/stdc++.h>
using namespace std;

#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
typedef long long LL;
const int maxn = 100010;

//离散化
int a[maxn], b[maxn], num;
int getidx(int v){ return lower_bound(b+1,b+num+1,v)-b; }

//主席树,查询区间比k小的数的个数
struct HJTTree{
typedef long long LL;
#define maxn 100010
struct node{ int sum, l, r; }hjt[maxn*40];
int rt[maxn], cnt = 0;
void init(){ cnt = 0; }
inline int CreateNode(int sum, int l, int r){
int idx = ++cnt;
hjt[idx].sum = sum;
hjt[idx].l = l;
hjt[idx].r = r;
return idx;
}
void insert(int &p, int pp, int pos, int l, int r){
p = CreateNode(hjt[pp].sum+1, hjt[pp].l, hjt[pp].r);
if(l == r)return ;
int mid = l+r>>1;
if(pos <= mid)insert(hjt[p].l, hjt[pp].l, pos, l, mid);
else insert(hjt[p].r, hjt[pp].r, pos, mid+1,r);
}
int query(int u, int v, int h, int l, int r){
if(r <= h)return hjt[v].sum-hjt[u].sum;
int mid = l+r>>1;
if(h <= mid)return query(hjt[u].l, hjt[v].l, h, l, mid);
else return query(hjt[u].r,hjt[v].r, h, mid+1, r)+hjt[hjt[v].l].sum-hjt[hjt[u].l].sum;
}
}hjt;

int main(){
IOS;
int T; cin>>T;
while(T--){
int n, m; cin>>n>>m;
for(int i = 1; i <= n; i++){
cin>>a[i]; b[i] = a[i];
}
sort(b+1,b+n+1);
num = unique(b+1,b+n+1)-(b+1);
hjt.init();
for(int i = 1; i <= n; i++){
hjt.insert(hjt.rt[i], hjt.rt[i-1], getidx(a[i]), 1, num);
}
while(m--){
int l, r, h; cin>>l>>r>>h;
// l++; r++;
h = upper_bound(b+1,b+num+1,h)-b;
if(h != 1)cout<<hjt.query(hjt.rt[l-1], hjt.rt[r], h-1, 1, num)<<"\n";
else cout<<"0\n";
}
}
return 0;
}