数数

题目链接

数数

在给定 \(N\) 长的数组 \({A}\) 中进行 \(Q\) 次询问 \([L_i,R_i]\) 区间中不大于 \(H_i\) 的元素个数。

共包含 \(T\) 组数据。

输入格式

输入就像下面这样:

T
N Q
A1 A2 A3 ... AN
L1 R1 H1
L2 R2 H2
...
LQ RQ HQ
...

输出格式

\(T\) 组数据,每组都输出一行,包含 \(Q\) 个以空格分隔的整数,表示答案。

样例输入

1
10 3
0 5 2 7 5 4 3 8 7 7
3 9 6
4 6 0
2 4 2

样例输出

4 0 1

样例说明: \(A[3..9]=[2,7,5,4,3,8,7]\), 其中不大于 \(6\) 的元素数量为 \(4\)

数据规模

\(1≤N,Q≤10^5\)
\(0≤A_i,H≤10^9\)
\(1≤L≤R≤N\)
数据保证 \(∑N,Q≤10^5\)

解题思路

树状数组,双指针

离线做法:记录数组的位置,按值的大小排序,同时记录询问的时间,按 \(h\) 排序,从前往后遍历每次询问,每次将不大于 \(h_i\)\(a_i\) 的位置放入树状数组中,然后统计前缀和,由于后面大于 \(h_i\) 的位置对答案没有影响,所以暂时不把那些对答案无影响的位置加上去

  • 时间复杂度:\(O(nlogn+qlogq)\)

代码

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1e5+5;
int t,tr[N],n,Q,res[N];
PII a[N];
struct qu
{
	int l,r,h,id;
	bool operator<(qu &o)const
	{
		return h<o.h;
	}
}q[N];
int find(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void add(int x,int y)
{
	for(;x<=n;x+=x&-x)tr[x]+=y;
}
int ask(int x)
{
	int res=0;
	for(;x;x-=x&-x)res+=tr[x];
	return res;
}
int main()
{
    for(cin>>t;t;t--)
    {
    	memset(tr,0,sizeof tr);
    	cin>>n>>Q;
    	for(int i=1;i<=n;i++)
    	{
    		cin>>a[i].fi;
    		a[i].se=i;
    	}
    	sort(a+1,a+1+n);
    	for(int i=1;i<=Q;i++)
    	{
    		cin>>q[i].l>>q[i].r>>q[i].h;
    		q[i].id=i;
    	}
    	sort(q+1,q+1+Q);
    	for(int i=1,j=1;i<=Q;i++)
    	{
    		while(j<=n&&a[j].fi<=q[i].h)add(a[j++].se,1);
    		res[q[i].id]=ask(q[i].r)-ask(q[i].l-1);
    	}
    	for(int i=1;i<=Q;i++)cout<<res[i]<<' ';
    	puts("");
    }
    return 0;
}
posted @ 2022-03-04 09:08  zyy2001  阅读(43)  评论(0编辑  收藏  举报