您的位置:首页 > 其它

BZOJ 2506: calc【离线,值域分块

2016-11-14 21:16 357 查看
……看到这么鬼畜的不好维护的区间,考虑离线,从左到右添加数列中的数

因为值域是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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: