poj3468 树状数组解法(树状数组维护区间更新)
来源:互联网 发布:琪琪影院软件下载 编辑:程序博客网 时间:2024/05/16 16:07
这个题目是一个经典的线段树维护区间跟新问题。后来在看书装数组维护区间和的时候,发现有好多大神说这个题目也可以用树状数组来解。后来就也研究了一下。当然,和大多数用树状数组解的题目的思路差不多,只是这个不太好想。根据树状数组的特点:树状数组是维护前缀和的经典做法,它的更新是对数组中的一个元素的,就是每次更新只能改变一个元素的值。那么,如何用树状数组来维护区间更新呢。源数据放在a[]数组中。这就需要构造数组(这也是树状数组题目的大多做法,也是树状数组解题 的一个难点)。如何构造数组:构造数组c[],d[];其中:c[i]表示区间[i,n]的增量,那么,更新(x,y,z)就比较简单为update_c(x,z),update_c(y+1,-z)(即:c[x]+z,c[y+1]-z)。求和:s[x] = a[1]+a[2]+...+a[x]+c[1]*x+c[2]*(x-1)+...c[x]*(x+1-i) = {a[1]+a[2]+...+a[x]} + {(x+1)*(c[1]+c[2]+...+c[x])} - {1*c[1]+2*c[2]+...+x*c[x]};那么,我们令d[i] = c[i]*i;则d[]的更新为:update_d(x,x*c[x]),update_d(y+1,(y+1)*c[y+1]);
构造依据:树状数组的特点,求和:求的是前缀和;更新:一次只能改变一个元素的值。
这样就可以用树状数组来解决区间更新的问题了;
poj3468
//树状数组维护区间更新求和 #include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAX 100010#define ll long longusing namespace std;ll c[MAX],d[MAX],a[MAX];int n,q;int lowbit(int x){return x&(-x);}void update1(int x, ll u){ //更新c数组for (int i = x; i<=n; i+=lowbit(i)){c[i] += u;}}void update2(int x, ll u){ //更新d数组for (int i = x; i<=n; i+=lowbit(i)){d[i] += u;}}ll sum1(int x){<span style="white-space:pre"></span>//c数组求前缀和ll s = 0;for (int i = x; i>0; i-=lowbit(i)){s += c[i];}return s;}ll sum2(int x){<span style="white-space:pre"></span>//d数组求前缀和ll s = 0;for (int i = x; i>0; i-=lowbit(i)){s += d[i];}return s;}int main(){while (scanf("%d%d",&n,&q) != EOF){memset(a,0,sizeof(a));memset(c,0,sizeof(c));memset(d,0,sizeof(d));ll t;for (int i = 1; i<=n; i++){scanf("%lld",&t);a[i] = a[i-1] + t;}char s[5];while (q--){scanf("%s",s);int x,y;ll z;if (s[0] == 'Q'){scanf("%d%d",&x,&y);ll t1 = a[y] - a[x-1];ll t2 = (y+1)*sum1(y) - x*sum1(x-1);ll t3 = sum2(y) - sum2(x-1);printf("%lld\n",t1+t2-t3);}else{scanf("%d%d%lld",&x,&y,&z); //注意理解如何更新update1(x,z);update1(y+1,-z);update2(x,x*z);update2(y+1,-(y+1)*z);}}}return 0;}
0 0
- poj3468 树状数组解法(树状数组维护区间更新)
- 树状数组 区间更新 POJ3468
- poj3468 树状数组(区间更新)
- [POJ3468] 区间操作 - 树状数组
- poj3468树状数组之区间更新+区间询问
- poj3468-树状数组 一维 区间更新 区间查询
- POJ3468 树状数组的区间更新和区间求和
- poj3468(树状数组)
- poj3468 树状数组的区间快速更新和查询
- poj3468(树状数组:区间修改 区间求和)
- 树状数组~poj3468~区间修改 区间查询
- 树状数组 区间更新
- 树状数组区间更新
- poj3468--A Simple Problem with Integers(树状数组解法)
- poj 3468 树状数组解法(解决区间更新,区间求和)
- poj 3468 树状数组解法(解决区间更新,区间求和)
- poj 3468 树状数组解法(解决区间更新,区间求和)
- 树状数组维护区间最大值
- leetcode: Interleaving String
- iOS图像拉伸,stretchableImageWithLeftCapWidth:topCapHeight:
- [游戏]传染病CONTAGION
- Leetcode:3Sum Closest
- MyBatis3整合Spring3的Transaction事务处理
- poj3468 树状数组解法(树状数组维护区间更新)
- 【知乎】2014年放弃阿里巴巴 offer 的人为什么格外多?
- 循环赛日程表java写
- RootSudo
- 文档聚类概述
- 软件开发过程(CMMI/RUP/XP/MSF)是与非?
- Android NDK编程(一) Windows下环境配置
- leetcode:3Sum
- 外网访问控制网络备忘