[数学][差分]JZOJ 4744

Description

 

Input

Output

 

Sample Input

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

Sample Output

2
1
 

Data Constraint

分析

我们可以从模数上面思考

我们看看,如果设一个g[i][j]表示模j为i的数的数量

那么我们每次得到一个数,模一遍,复杂度为O(np)

然后再设h[i]表示为i的数的数量

i如果模p等于q,则满足p*k+q=i

我们只需要枚举k,复杂度为O(n ai/p)

显然得知当p为根号a时最优

把询问拆成差分查询即可

 

#include <iostream> 
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N],h[100001],g[101][101],ans[N];
struct Query {
    int r,p,q,id,del;
}q[2*N];
int cnt;

bool CMP(Query a,Query b) {
    return a.r<b.r;
}

int Calc(int x) {
    int ans=0;
    if (q[x].p>=100) for (int i=0;i<=10000/q[x].p;i++) ans+=h[i*q[x].p+q[x].q];
    else ans=g[q[x].q][q[x].p];
    return ans;
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=m;i++)
        ++cnt,scanf("%d%d%d%d",&q[cnt].r,&q[cnt+1].r,&q[cnt].p,&q[cnt].q),q[cnt].id=i,q[cnt].del=-1,q[cnt].r--,
        ++cnt,q[cnt].p=q[cnt-1].p,q[cnt].q=q[cnt-1].q,q[cnt].id=i,q[cnt].del=1;
    sort(q+1,q+cnt+1,CMP);
    int j=1;
    while (j<=cnt&&q[j].r==0) j++;
    for (int i=1;i<=n;i++) {
        h[a[i]]++;
        for (int k=1;k<=100;k++) g[a[i]%k][k]++;
        while (j<=cnt&&q[j].r==i) {
            ans[q[j].id]+=q[j].del*Calc(j);
            j++;
        }
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
View Code

 

posted @ 2019-03-21 20:51  Vagari  阅读(120)  评论(0编辑  收藏  举报