【三维树状数组与离散化】HDU 4267——A Simple Problem with Integers

来源:互联网 发布:java虚拟主机管理系统 编辑:程序博客网 时间:2024/05/17 00:51

题目:点击打开链接

长春赛区网络赛的题,也是2012年五大区网络赛第一场的第一个题,当时智商拙计,连树状数组和线段树的大名也没有听说过,居然以为是模拟偷笑被大神们好一阵修理。。

现在学习了树状数组,写起来也是磕磕绊绊,参阅了若干大神的若干资料,终于凑合了这个三维树状数组的更新。和一般的树状数组不同的是,为节约时间,尽量不TLE,我们的第二维是K,第三维是a%k(为什么是这个呢?原式中的(i-a)%k==0可以移向的。。更新的时候也是按照这个余数来跳着更新,忽忽悠悠就这么过了。。。。

//(i-a)%k==0可以换成i%k==a%k,这个思路转自大神blog #include <iostream>#include <stdio.h>#include <string.h>using namespace std;int numpack[60000],N;int c[60000][11][11];  //第二维为k,第三维为mod int lowbit(int x){return x&(-x);}void update_addnum(int pos,int delta,int mod,int k)  //修改成三维的 {for(int i=pos;i>0;i-=lowbit(i)){c[i][k][mod]+=delta;}}void update_subnum(int pos,int delta,int mod,int k)  //修改成三维的 {for(int i=pos;i>0;i-=lowbit(i)){c[i][k][mod]-=delta;}}int find_add(int x){int a=x;int result=0;for(int i=x;i<=N;i+=lowbit(i)){for(int j=1;j<=10;j++){result+=c[i][j][a%j];      //把第二维遍历一遍 }}return result;}int main(){while(scanf("%d",&N)!=EOF){memset(numpack,0,sizeof(numpack));memset(c,0,sizeof(c));for(int i=1;i<=N;i++){scanf("%d",&numpack[i]);}int opernum,oper,a,b,c,k;scanf("%d",&opernum);while(opernum--){scanf("%d",&oper);if(oper==1){scanf("%d%d%d%d",&a,&b,&k,&c);update_addnum(b,c,a%k,k);update_subnum(a-1,c,a%k,k);}if(oper==2){int idx;scanf("%d",&idx);int res=numpack[idx]+find_add(idx);//更新值加原始值 printf("%d\n",res);}}}return 0;}


原创粉丝点击