您的位置:首页 > 其它

URAL 2062 Ambitious Experiment(分块)

2017-02-17 09:58 369 查看
【题目链接】 http://acm.timus.ru/problem.aspx?space=1&num=2062

【题目大意】

  给出两个操作,操作一给出区间[l,r],对l到r中的每一个下标i,
  i,2*i,3*i……位置都增加x,操作二要求查询一个位置的当前值

【题解】

  在修改的时候,我们将增量只标识在i上,查询的时候,查询下标的因子和即可。
  考虑到这种查询方法需要sqrt(n)枚举判断因子,用二叉数据结构可能会超时,
  因此我们用分块nsqrt(n)修改,O(1)查询特定位置。

【代码】

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAX_SIZE=550,MAX_N=300010;
LL block[MAX_SIZE],u[MAX_SIZE][MAX_SIZE];
int n,m,a[MAX_N],op,x,l,r,size;
void add(int l,int r,int v){
int L=l/size,R=r/size;
if(L==R)for(int i=l%size;i<=r%size;i++)u[L][i]+=v;
else{
for(int i=l%size;i<size;i++)u[L][i]+=v;
for(int i=L+1;i<R;i++)block[i]+=v;
for(int i=0;i<=r%size;i++)u[R][i]+=v;
}
}
LL query(int x){
LL ans=0;
for(int i=1;i*i<=x;i++){
if(x%i==0){
int t=i-1;
ans+=block[t/size]+u[t/size][t%size];
if(i*i!=x){
int t=x/i-1;
ans+=block[t/size]+u[t/size][t%size];
}
}
}return ans;
}
int main(){
while(~scanf("%d",&n)){
memset(block,0,sizeof(block));
memset(u,0,sizeof(u));
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
scanf("%d",&m);
size=sqrt(n);
while(m--){
scanf("%d",&op);
if(op==1){
scanf("%d",&x);
printf("%lld\n",query(x)+a[x]);
}else{
scanf("%d%d%d",&l,&r,&x);
add(--l,--r,x);
}
}
}return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: