bzoj2506

題意:n個非負整數a[n],m個詢問,l,r,p,k,問l<=i<=r且a[i]%p=k的數的個數。

數據範圍:
0<n,m<=10^5,任意1<=i<=n滿足Ai<=10^4,0<p<=10^4,0<=k<p。

將詢問離線,將[l,r]分爲[1,l-1]和[1,r],同時記錄a[i]對100以內的數的模數和a[i]的數量,然後對p>100和p<=100分別按兩種記錄方式得到結果,這樣保證了查詢時間複雜度爲O(100m)

#include<bits/stdc++.h>
using namespace std;
int n, m, top, mx;
int a[100005];
int f1[105][105], f2[100005];
int ans[2][100005];
struct data1 { int x, f, p, k, num; }q[200005];
inline bool cmp(data1 a, data1 b)
{
	return a.x < b.x;
}
void add(int x)
{
	for (int i = 1; i <= 100; i++)
		f1[i][x % i]++;
	f2[x]++;
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		cin>>a[i], mx = max(mx, a[i]);
	for (int i = 1; i <= m; i++)
	{
		int l, r, p, k;
		scanf("%d%d%d%d", &l, &r, &p, &k);
		q[++top].x = l - 1; q[top].p = p; q[top].k = k; q[top].num = i;
		q[++top].x = r; q[top].p = p; q[top].k = k; q[top].num = i; q[top].f = 1;
	}
	sort(q + 1, q + top + 1, cmp);
	int now = 0;
	for (int i = 1; i <= top; i++)
	{
		while (now < q[i].x) { now++; add(a[now]); }
		int p = q[i].p, k = q[i].k;
		if (p <= 100)ans[q[i].f][q[i].num] = f1[p][k];
		else
			for (int j = k; j <= mx; j += p)
				ans[q[i].f][q[i].num] += f2[j];
	}
	for (int i = 1; i <= m; i++)
		printf("%d\n", ans[1][i] - ans[0][i]);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章