題目:添加鏈接描述
思路:先把數據離散化,按照權值建立主席樹,然後對於一個高度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;
}