题目:添加链接描述
思路:先把数据离散化,按照权值建立主席树,然后对于一个高度h,我们找的答案是区间中不大于h的数,那么我们求取了mid后,如果h大于mid,那么左子树的数都小于h所以要统计左子树的上的数量,然后继续递归求解右子树,一直下去直到叶节点,返回它的值就ok,还有就是我们查询的高度也是离散化之后的高度。upper_bound找的时候不要找飘了
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod (10007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 100000+100;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
return f*res;
}
struct node
{
int l,r,val;
}tree[maxn * 25];
int lsan[maxn],m,cnt,root[maxn],n,a[maxn],number = 1;
int getid(int x,int up) {
return lower_bound(lsan + 1,lsan + 1 + up,x) - lsan;
}
void update(int l,int r,int &now,int last,int v) {
tree[++cnt] = tree[last]; tree[cnt].val++; now=cnt; //建立主席树,顺带按照权值维护一下每个数的个数
if(l == r) return ;
int mid = middle;
if(v <= mid) update(l,mid,tree[now].l,tree[last].l,v);
else update(mid + 1,r,tree[now].r,tree[last].r,v);
}
int query(int l,int r,int l_rt,int r_rt,int k) {
if(r <= k ) return tree[r_rt].val-tree[l_rt].val; //整个左区间的数都不大于k 所以我们直接返回统计的数量,不需要递归
if(l == r) return tree[r_rt].val - tree[l_rt].val;
int mid = middle;
if(k <= mid) return query(l,mid,tree[l_rt].l,tree[r_rt].l,k); //去左区间找
else return query(mid + 1,r,tree[l_rt].r,tree[r_rt].r,k) + tree[tree[r_rt].l].val - tree[tree[l_rt].l].val; //去右区间找,同时加上左区间的。
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
cnt = 0;
memset(lsan,0,sizeof(lsan));
memset(root,0,sizeof(root));
memset(tree,0,sizeof(tree));
scanf("%d%d",&n,&m);
for(int i = 1;i <= n ;i++) scanf("%d",&a[i]),lsan[i] = a[i];
sort(lsan + 1,lsan + 1 + n);
int tot = unique(lsan + 1,lsan + 1 + n) - lsan - 1;
for(int i = 1;i <= n; ++i) {
update(1,tot,root[i],root[i-1],getid(a[i],tot));
}
printf("Case %d:\n",number++);
for(int i = 1;i <= m; ++i) { //这里m我写成了n,re10多次,艹
int ql,qr,up;
scanf("%d%d%d",&ql,&qr,&up);
ql++;qr++;
int pos = upper_bound(lsan+1,lsan+1+tot,up)-lsan;
// printf("pos=%d\n",pos);
if(pos == 1) { printf("0\n"); continue; }
else if(pos > tot) { printf("%d\n",qr + 1 - ql); continue; }
else
printf("%d\n",query(1,tot,root[ql-1],root[qr],pos-1));
}
}
return 0;
}