……看到这么鬼畜的不好维护的区间,考虑离线,从左到右添加数列中的数
因为值域是1e4,考虑p<=100和p>100的情况。
p<=100的情况下,O(√值域)地更新,O(1)地查询;p>100的时候,O(1)地更新,O(√值域)地查询
添加每个数的时候,对于p<=100的情况的贡献直接累加;对于p>100的显然只有100左右个数对答案有贡献,于是枚举就好了
……反正这种套路我应该学不会x
#include<bits/stdc++.h>
#define MAXN 100005
#define MX 10005
using namespace std; int n,m,mx;
int a[MAXN];
struct t1{
int opt,pos,id,p,x;
bool operator < (const t1 &ano) const{
return pos < ano.pos;
}
}Q[MAXN<<1];
int f1[105][105],f2[MX];
int ans[MAXN];
int read_l,read_r,read_p,read_x;
int main(){
// freopen("1.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",a+i) , mx = max(mx,a[i]);
for(int i=1;i<=m;++i){
scanf("%d%d%d%d",&read_l,&read_r,&read_p,&read_x);
Q[i] = (t1){-1,read_l-1,i,read_p,read_x};
Q[i+m] = (t1){1,read_r,i,read_p,read_x};
}
int m2 = m<<1;
sort(Q+1,Q+m2+1);
for(int i=1,now=0;i<=m2;++i){
while(now<Q[i].pos){
++now;
for(int j=1;j<=100;++j) ++f1[j][a[now]%j];
++f2[a[now]];
}
if(Q[i].p<=100)
ans[Q[i].id] += Q[i].opt * f1[Q[i].p][Q[i].x];
else{
int tmp = 0;
for(int j=Q[i].x;j<=mx;j+=Q[i].p)
tmp += f2[j];
ans[Q[i].id] += Q[i].opt * tmp;
}
}
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}

本文介绍了一种离线处理区间更新与查询的方法,通过预处理将不同范围内的操作进行分类,实现高效的更新与查询效率。针对不同规模的质数采用不同的策略,小质数时使用桶状结构进行更新,大质数时则采用枚举的方式。
1205

被折叠的 条评论
为什么被折叠?



