数数
题目描述:
给定长度为
n
的数组a[i]
,进行Q次询问,每次询问都查询[L, R]
中小于等于H
的元素的个数
思路:
比较显然的离线+树状数组题目
我们可以将所有询问按照
H
从小到大排序,把数组a[i]
也按照从小到大的顺序进行排序,同时记录原位置的下标对于每次询问
[l, r, h]
我们将小于等于h
的所有a[i]
插到树状数组里面,插的是他在原数组的位置输出的时候我们查询树状数组的
r
减去l-1
的答案就行
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;
#define lowbit(x) (x&(-x))
#define MAX 300000 + 50
int n, m, k, x;
pii fuck[MAX];
struct ran{
int l, r, c, id;
bool operator < (const ran &x)const{
return c < x.c;
}
}ar[MAX];
int ans[MAX];
int tr[MAX];
void add(int id){
while(id <= n){
++tr[id];
id += lowbit(id);
}
}
int getans(int id){
int ans = 0;
while(id){
ans += tr[id];
id -= lowbit(id);
}
return ans;
}
void work(){
cin >> n >> m;
for(int i = 0; i <= 2*n; ++i)tr[i] = 0;
for(int i = 1; i <= n; ++i){
cin >> fuck[i].first;
fuck[i].second = i;
}
sort(fuck + 1, fuck + 1 + n);
for(int i = 1; i <= m; ++i){
cin >> ar[i].l >> ar[i].r >> ar[i].c;
ar[i].id = i;
}
sort(ar + 1, ar + 1 + m);
int id = 0;
for(int i = 1; i <= m; ++i){
while(id+1<=n && fuck[id+1].first <= ar[i].c){
++id;
add(fuck[id].second);
}
ans[ar[i].id] = getans(ar[i].r) - getans(ar[i].l - 1);
}
for(int i = 1; i <= m; ++i)cout << ans[i] << ' ';
cout << endl;
}
int main(){
io;
int t;cin>>t;while(t--)
work();
return 0;
}