Ambitious Experiment URAL

来源:互联网 发布:深圳大数据培训 编辑:程序博客网 时间:2024/05/29 13:52

传送门:URAL - 2062

题意:给定n个数的初始值,和两种操作:

1.询问第i个数是多少

2.给定l,r,d,将i,2*i,3*i...位置上的数加d,l<=i<=r.

思路:采用平方分割算法,也叫块状数组,算法思想大致就是讲整个区间分成长度为sqrt(n)的块,然后每次更新如果包括完整的块就直接维护整个块,然后将剩余部分单点更新。具体讲解见挑程序设计第二版P183.

就本题来说,对第i个数有贡献的数的下标就是i的所有因数。因此询问某个点时暴力因数分解一下然后加和就好了。

代码:

#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<math.h>#include<algorithm>#include<queue>#include<stack>#include<set>#include<vector>#include<map>#define ll long long#define pi acos(-1)#define inf 0x3f3f3f3f#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;typedef pair<int,int>P;const int MAXN=300010;int n,num[MAXN];int L[3000],R[3000],id[MAXN];ll interval[3000],own[MAXN];void init(){int t=sqrt(n);int cnt=n/t;if(n%t)cnt++;for(int i=1;i<=cnt;i++){L[i]=(i-1)*t+1;R[i]=(i)*t;}for(int i=1;i<=n;i++)id[i]=(i-1)/t+1;}void update(int l,int r,int d){if(id[l]==id[r]){for(int i=l;i<=r;i++)own[i]+=d;return ;} for(int i=l;i<=R[id[l]];i++)own[i]+=d;for(int i=id[l]+1;i<=id[r]-1;i++)interval[i]+=d;for(int i=L[id[r]];i<=r;i++)own[i]+=d;}ll solve(int k){ll ans=0;for(int i=1;i*i<=k;i++){if(k%i==0){ans+=interval[id[i]]+own[i];if(i*i!=k)ans+=interval[id[k/i]]+own[k/i];}}return ans;}int main(){int m,l,r,d,k;cin>>n;for(int i=1;i<=n;i++)scanf("%d",num+i);init();cin>>m;while(m--){scanf("%d",&k);if(k==2){scanf("%d%d%d",&l,&r,&d);update(l,r,d);}else{scanf("%d",&k);printf("%lld\n",solve(k)+num[k]);}}    return 0;}

网上有很多用树状数组解这个题的,但是基本上都是卡过去的,时间上限很紧,2700+ms。说不准什么时候T了。

0 0
原创粉丝点击