您的位置:首页 > 其它

HDOJ 4267 A Simple Problem with Integers

2012-09-11 16:07 204 查看
题意:维护一个整数序列,支持2种操作:

1 a b k c将区间[a b]中满足(i-a)%k==0的数加上c;

2 x查询第x个数的值。

数据范围:整数个数N<=50000,操作次数Q<=50000,1<=k<=10

分析:此题关键在于处理修改操作,我们发现修改是等间隔的,所以可以将数组拆开如下:

k=1时,间隔为0:

1 2 3 4 5 6 7 8 9 10……

k=2时,间隔为1:

1 3 5 7 9 ……

2 4 6 8 10……

k=3时,间隔为2:

1 4 7 10……

2 5 8 ……

3 6 9 ……

按以上拆法,可以得到55个整数序列,每次修改都是对其中一个序列进行的连续修改,由于每个数均在10个序列中出现,所以查询操作是10个序列的查询结果的和。所以需用55棵线段树来维护这55个序列,由于N很大,可能会MLE,这时就要想到树状数组了……

View Code

#include <stdio.h>
#include <string.h>
#define N 50001
int a
,n,m;
int d[10][10]
;
struct pro
{
void init()
{
for(int i=1;i<=n;i++)   scanf("%d",&a[i]);
for(int i=0;i<10;i++)
{
for(int j=0;j<=i;j++)
{
memset(d[i][j],0,sizeof(d[0][0][0])*(n+1));
}
}
}
void query()
{
int x;
scanf("%d",&x);
int ans=a[x];
for(int k=1;k<=10;k++)
{
int j=(x-1)%k;
for(int i=(x-j-1)/k+1;i;i-=i&-i)
{
ans+=d[k-1][j][i];
}
}
printf("%d\n",ans);
}
void update()
{
int x,y,k,z;
scanf("%d%d%d%d",&x,&y,&k,&z);
int j=(x-1)%k;
for(int i=(x-j-1)/k+1;i<=n;i+=i&-i)    d[k-1][j][i]+=z;
for(int i=(y-j-1)/k+2;i<=n;i+=i&-i)  d[k-1][j][i]-=z;
}
}p;
int main()
{
while(~scanf("%d",&n))
{
p.init();
scanf("%d",&m);
while(m--)
{
int opt;
scanf("%d",&opt);
if(opt==1)  p.update();
else    p.query();
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: