zoukankan      html  css  js  c++  java
  • [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
    ", ans[i]);
    	
    	return 0;
    }
    
  • 相关阅读:
    CentOS7.4安装Docker
    责任链模式
    策略模式
    状态模式
    解释器模式
    备忘录模式
    中介者模式
    观察者模式
    迭代器模式
    private、default、protected和public的作用域
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6733269.html
Copyright © 2011-2022 走看看