[BZOJ2506]calc

[BZOJ2506]calc

试题描述

给一个长度为n的非负整数序列A1,A2,…,An。现有m个询问,每次询问给出l,r,p,k,问满足l<=i<=r且Ai mod p = k的值i的个数。

输入

第一行两个正整数n和m。
第二行n个数,表示A1,A2,…,An。
以下m行,每行四个数分别表示l,r,p,k。满足1<=l<=r<=n。

输出

对于每个询问,输出一行,表示可行值i的个数。

输入示例

5 2
1 5 2 3 7
1 3 2 1
2 5 3 0

输出示例

2
1

数据规模及约定

0<n,m<=10^5,任意1<=i<=n满足Ai<=10^4,0<p<=10^4,0<=k<p。

题解

首先这个问题满足区间减法,所以可以离线搞,把一个询问拆成两个询问(即“右端点”减去“左端点-1”)。然后每个询问变成这个样子:在一个前缀中满足 Ai mod p = k 的 i 有多少个。

因为是每个前缀,所以我们可以按照右端点从左到右排序,然后每次右端点往右移一个单位就是往集合中加入一个数,不带删除。那么我们可以对 p 的大小分类讨论,令 B = max{Ai},若 p > sqrt(B) 那么直接暴力找 {k, k + p, k + 2p, k + 3p, ...} 这些数都有多少个并累加;若 p ≤ sqrt(B) 那么因为 p 和 k 都小于等于 sqrt(B),我们就可以对于所有的数对 (p, k) 维护 Ai mod p = k 的 i 有多少个。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
	return x * f;
}

#define maxn 100010
#define maxa 10010
#define maxsqr 110

int n, A[maxn], sma[maxsqr][maxsqr], lar[maxa], ans[maxn];

struct Que {
	int x, p, k, id, tp;
	Que() {}
	Que(int _1, int _2, int _3, int _4, int _5): x(_1), p(_2), k(_3), id(_4), tp(_5) {}
	bool operator < (const Que& t) const { return x < t.x; }
} qs[maxn<<1];

int main() {
	n = read(); int q = read(), cq = 0, m = 0;
	for(int i = 1; i <= n; i++) A[i] = read(), m = max(m, A[i]);
	for(int i = 1; i <= q; i++) {
		int l = read(), r = read(), p = read(), k = read();
		qs[++cq] = Que(l - 1, p, k, i, -1);
		qs[++cq] = Que(r, p, k, i, 1);
	}
	
	sort(qs + 1, qs + cq + 1);
	m = sqrt(m);
	for(int i = 1, j = 1; i <= cq; i++) {
		while(j <= n && j <= qs[i].x) {
			for(int k = 1; k <= m; k++) sma[k][A[j]%k]++;
			lar[A[j]]++;
			j++;
		}
		if(qs[i].p <= m) ans[qs[i].id] += qs[i].tp * sma[qs[i].p][qs[i].k];
		else {
			int sum = 0;
			for(int val = qs[i].k; val < maxa; val += qs[i].p) sum += lar[val];
			ans[qs[i].id] += qs[i].tp * sum;
		}
	}
	
	for(int i = 1; i <= q; i++) printf("%d\n", ans[i]);
	
	return 0;
}

 

posted @ 2017-04-19 14:18  xjr01  阅读(174)  评论(0编辑  收藏  举报