【黑科技】用树状数组解决区间修改查询问题
2017-08-14 21:55
246 查看
遇到区间查询修改,相信大家一般用的都是线段树,
但常数远远没有树状数组优秀,
这里就来谈谈如何用树状数组解决区间问题
(同时可以用于多维问题)
首先,相信大家一定会用树状数组做区间加,单点查询的问题,
差分一下即可;
那么对于区间查询,怎么做呢?
要做到区间查询,就要能计算一个点的值对后面的值的影响,
多开一个数组F[i]=(n-i+1)*f[i],(f为用来差分的数组)
差分的话当然是这个点的值对后面的每个点都有影响,所以权值乘上那么多,
但很显然,在计算区间是,它的影响没有那么大,
设查询的区间是l,r,那么它在答案中应该是:(r−i+1)∗f[i]=F[i]−(n−r)∗f[i],
发现(n-r)对于任意的f[i]都是一定的,也就是可以区间求和以后直接乘上(n-r)减掉F多出来的部分,再加上l之前的影响,
这样既可实现用树状数组解决区间修改查询问题,
那么现在问题来了,如何用树状数组实现二维或多维的求和,
以二维为例,
对平面上的一个矩形加/减,求矩形里点的和,
我们需要多开3个数组,
F1[i][j]=(m-j+1)*(n-i+1)*f[i],
F2[i][j]=(n-i+1)*f[i],
F3[i][j]=(m-j+1)*f[i],
用矩阵和的套路,减掉右边左边,加上右下角的,即可,
对于前面的影响,与处理后面的差不多,
(这个需要大家自己感受一下,实在不会就看标吧)
(重点在Gans这个函数)
但常数远远没有树状数组优秀,
这里就来谈谈如何用树状数组解决区间问题
(同时可以用于多维问题)
首先,相信大家一定会用树状数组做区间加,单点查询的问题,
差分一下即可;
那么对于区间查询,怎么做呢?
要做到区间查询,就要能计算一个点的值对后面的值的影响,
多开一个数组F[i]=(n-i+1)*f[i],(f为用来差分的数组)
差分的话当然是这个点的值对后面的每个点都有影响,所以权值乘上那么多,
但很显然,在计算区间是,它的影响没有那么大,
设查询的区间是l,r,那么它在答案中应该是:(r−i+1)∗f[i]=F[i]−(n−r)∗f[i],
发现(n-r)对于任意的f[i]都是一定的,也就是可以区间求和以后直接乘上(n-r)减掉F多出来的部分,再加上l之前的影响,
这样既可实现用树状数组解决区间修改查询问题,
那么现在问题来了,如何用树状数组实现二维或多维的求和,
以二维为例,
对平面上的一个矩形加/减,求矩形里点的和,
我们需要多开3个数组,
F1[i][j]=(m-j+1)*(n-i+1)*f[i],
F2[i][j]=(n-i+1)*f[i],
F3[i][j]=(m-j+1)*f[i],
用矩阵和的套路,减掉右边左边,加上右下角的,即可,
对于前面的影响,与处理后面的差不多,
(这个需要大家自己感受一下,实在不会就看标吧)
(重点在Gans这个函数)
void change(int x,int y,int e) { if(x>n||y>m)return; for(int i=x;i<=n;i+=NX(i)) for(int j=y;j<=m;j+=NX(j)) { f[i][j]+=e; f1[i][j]=(f1[i][j]+e*(n-x+1)*(m-y+1))%mo; f2[i][j]=(f2[i][j]+e*(n-x+1))%mo; f3[i][j]=(f3[i][j]+e*(m-y+1))%mo; } } void find(int x,int y) { fd1=fd2=fd3=fd=0; for(int i=x;i;i-=NX(i)) for(int j=y;j;j-=NX(j)) { fd+=f[i][j]; fd1=(fd1+f1[i][j])%mo; fd2=(fd2+f2[i][j])%mo; fd3=(fd3+f3[i][j])%mo; } } void add(int x,int y,int x1,int y1) { change(x,y,1); change(x,y1+1,-1); change(x1+1,y,-1); change(x1+1,y1+1,1); } int Gans(int x,int y,int x1,int y1) { LL s,s1,s2,s3; find(x-1,y1);s=fd,s1=fd1,s2=fd2,s3=fd3; find(x-1,y-1);s-=fd,s1-=fd1,s2-=fd2,s3-=fd3; LL t=0; t=(s3-s*(m-y1))%mo*(x1-x+1)%mo; find(x1,y-1);s=fd,s1=fd1,s2=fd2,s3=fd3; find(x-1,y-1);s-=fd,s1-=fd1,s2-=fd2,s3-=fd3; t=(t+(s2-s*(n-x1))%mo*((y1-y+1))%mo)%mo; find(x-1,y-1);s=fd,s1=fd1,s2=fd2,s3=fd3; t=(t+s*(y1-y+1)%mo*(x1-x+1))%mo;//这是前面的影响 find(x1,y1);s=fd,s1=fd1,s2=fd2,s3=fd3; find(x-1,y1);s-=fd,s1-=fd1,s2-=fd2,s3-=fd3; find(x1,y-1);s-=fd,s1-=fd1,s2-=fd2,s3-=fd3; find(x-1,y-1);s+=fd,s1+=fd1,s2+=fd2,s3+=fd3; s1=s1-s3*(n-x1)-s2*(m-y1);s1=(s1%mo+mo)%mo; s=s%mo; s1=(s1+(n-x1)*(m-y1)%mo*s)%mo; return (s1+t)%mo; }
相关文章推荐
- 树状数组处理区间查询和区间修改的问题
- [模板]-树状数组③-区间修改+区间查询
- hdu 4970 Killing Monsters 【树状数组(区间修改,点查询)】
- 不修改SQL_Latin1_General_CP1_CI_AS 字符集 解决中文条件查询问题
- 【填坑】可持久化线段树解决无修改的区间k大问题
- 【树状数组区间修改单点查询】HDU 4031 Attack
- 树状数组进阶(区间修改+单点查询)
- 【BZOJ 3110】 [Zjoi2013]K大数查询 整体二分+树状数组区间修改
- 用树状数组解决区间查询问题
- UVALive 4730 - Kingdom 树状数组区间修改单点查询
- 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询
- A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
- 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
- 高级树状数组——区间修改区间查询、二维树状数组
- 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改
- 【转】【小结】树状数组的区间修改与区间查询
- 【小结】树状数组的区间修改与区间查询
- 树状数组解决区间问题(参考博客)
- 重置mysql Root用户密码及修改默认字符集一般就算设置了表的默认字符集为utf8并且通过UTF-8编码发送查询,你会发现存入数据库的仍然是乱码。问题就出在这个connection连接层上。 解决
- 树状数组应用之——区间修改 点查询