hdu4267 A Simple Problem with Integers(树状数组区间更新点查询)

题目链接:点击打开链接

题意描述:

给定一个数组,有两种操作:

操作一:a b k c 对于区间a~b之间的元素如果下标满足(i-a)%k=0则给元素i加上c

操作二:a          查询下标为a的元素当前值

解题思路:

1、首先这个涉及到区间修改点查询,所以应该想到使用树状数组或线段树

2、修改的区间是不连续的,为了使不连续可以转换为连续的,我们对每种情况进行枚举,有55种情况

即对k=1   有0

        k=2   有0 、1

        k=3    有0、1、2

···

        k=10   有0、1、2、3、4、5、6、7、8、9

所以我们可以声明一个三维数组c[k][i][j]:其中k%i=j的元素,表示k属于i,j这个树状数组

对于操作一:我们只需更改a[MAXN][k][a%k]这个树状数组内的连续区间,即

update(a,c);

update(b+1,-c);

对于a、b之间的不满足a%k的元素虽然我们也更新了,但是我们在查询的时候不会在a[MAXN][k][a%k]这个树状数组中查询,所以这个也就没有关系了

对于操作二:我们只需要查询a[a][i][a%i]即可,其中i从1到10,累加起来就可以了。最后加上d[a](位置a的初始值)


代码:

#include <cstdio>
#include <cstring>
#define MAXN 50010
using namespace std;

int num[MAXN],n;
int cnt[MAXN][11][10];
int inline lowbit(int x){
    return x&(-x);
}
void inline update(int x,int k,int mod,int add){
    while(x<=n){
        cnt[x][k][mod]+=add;
        x+=lowbit(x);
    }
}
int inline sum(int x,int a){
    int s=0;
    while(x>0){
        for(int i=1;i<=10;++i) s+=cnt[x][i][a%i];
        x-=lowbit(x);
    }
    return s;
}
int main(){
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;++i) scanf("%d",&num[i]);
        memset(cnt,0,sizeof(cnt));
        int m; scanf("%d",&m);
        while(m--){
            int op,a,b,k,add;
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d%d",&a,&b,&k,&add);
                update(a,k,a%k,add);
                update(b+1,k,a%k,-add);
            }
            else
            {
                scanf("%d",&a);
                printf("%d\n",sum(a,a)+num[a]);
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值