POJ 3468(树状数组 && 线段树)
2017-04-27 15:25
501 查看
树状数组:
题意:
给出n个数。有两种操作,分别是对对第i到第j个数全部加v,求出第i到第j个数之和。
思路:
基础的树形数组,不过最基础的树形数组是只能对一个数相加,对1~i之间求和,这
里不适用,所以要想办法,于是这里用了两个树形数组进行维护分别代表的是,原数
据的树形数组和,一个代表的是从i到n的增量,求和的时候需要从原数据的和+增量。
线段树
思路:
这种题很少需要什么思路,只是要深度理解线段树的构建过程,了解每一个语句的作用。
注意点
lazy的作用是记录每一个线段树节点的变化值
lazy有一个思想就是,变化只是先存在与当下,在update里面并没有向子树更新
其奥妙在于在query之中如果需要子树的值便会更新,这样可以减少一定的操作。
题意:
给出n个数。有两种操作,分别是对对第i到第j个数全部加v,求出第i到第j个数之和。
思路:
基础的树形数组,不过最基础的树形数组是只能对一个数相加,对1~i之间求和,这
里不适用,所以要想办法,于是这里用了两个树形数组进行维护分别代表的是,原数
据的树形数组和,一个代表的是从i到n的增量,求和的时候需要从原数据的和+增量。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 200005; typedef long long LL; LL n,m; LL bit0[MAXN],bit1[MAXN]; LL sum(LL *b,LL i) { LL s = 0; while(i > 0) { s += b[i]; i -= i&(-i); } return s; } void add(LL *b,LL i,LL v) { while(i <= n) { b[i] += v; i += i&(-i); } } int main() { //freopen("in.txt","r",stdin); LL i,k; LL a,b,c; while(scanf("%lld%lld",&n,&m) != EOF) { memset(bit1,0,sizeof(bit1)); memset(bit0,0,sizeof(bit0)); for(i = 1;i <= n; i++) { LL temp; scanf("%lld",&temp); add(bit0,i,temp); } char ch[10]; LL ans; for(k = 0;k < m; k++) { scanf("%s",ch); if(ch[0] == 'C') { scanf("%lld%lld%lld",&a,&b,&c); add(bit0,a,-c*(a-1)); add(bit0,b+1,b*c); add(bit1,a,c); add(bit1,b+1,-c); } else { ans = 0; scanf("%lld%lld",&a,&b); ans += sum(bit0,b) + sum(bit1,b)*b; ans -= (sum(bit0,a-1) + sum(bit1,a-1)*(a-1)); printf("%lld\n",ans); } } } return 0; }
线段树
思路:
这种题很少需要什么思路,只是要深度理解线段树的构建过程,了解每一个语句的作用。
注意点
lazy的作用是记录每一个线段树节点的变化值
lazy有一个思想就是,变化只是先存在与当下,在update里面并没有向子树更新
其奥妙在于在query之中如果需要子树的值便会更新,这样可以减少一定的操作。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 typedef long long LL; const int maxn = 100005; int n,m; LL sum[maxn<<2]; LL lazy[maxn<<2]; void PushUp(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt) { lazy[rt] = 0; if(l == r) { scanf("%lld",&sum[rt]); return ; } int m = (l+r)>>1; build(lson); build(rson); PushUp(rt); } void PushDown(int rt,int m) { if(lazy[rt]) { lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; sum[rt<<1] += (m-(m>>1))*lazy[rt]; sum[rt<<1|1] += (m>>1)*lazy[rt]; lazy[rt] = 0; } } LL query(int L,int R,int l,int r,int rt) { if(l >= L && r <= R) { return sum[rt]; } PushDown(rt,r-l+1); int m = (l+r)>>1; LL ans = 0; if(L <= m) ans += query(L,R,lson); if(R > m) ans += query(L,R,rson); return ans; } void update(int L,int R,int c,int l,int r,int rt) { if(l >= L && r <= R) { lazy[rt] += c; sum[rt] += (LL)c*(r-l+1); return ; } PushDown(rt,r-l+1); int m = (l+r)>>1; if(L <= m) update(L,R,c,lson); if(R > m) update(L,R,c,rson); PushUp(rt); } int main() { //freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m) != EOF) { build(1,n,1); int a,b,c; char op[2]; while(m--) { scanf("%s",op); if(op[0] == 'Q') { scanf("%d%d",&a,&b); printf("%lld\n",query(a,b,1,n,1)); } else { scanf("%d%d%d",&a,&b,&c); update(a,b,c,1,n,1); } } } return 0; }
相关文章推荐
- 模板(线段树 + 树状数组 + 区间修改 + 区间查询)eg:POJ 3468 - A Simple Problem with Integers
- POJ-2155-Matrix(二维树状数组 & 二维线段树)
- POJ 3468 A Simple Problem with Integers【线段树/树状数组】
- poj 3468 A Simple Problem with Integers 树状数组 或 线段树
- 【POJ】2299 - Ultra-QuickSort(离散化 & (树状数组 | 线段树))
- poj-3468 A Simple Problem with Integers(线段树,树状数组区间求和)
- poj 3468 A Simple Problem with Integers (线段树区间更新 + 树状数组区间更新)
- poj 3468 A Simple Problem with Integers(线段树区间更新 or 树状数组区间更新)
- poj-3468 线段树和树状数组的区间更新及求和
- poj 3468 树状数组解法(解决区间更新,区间求和)
- poj&nbsp;3067&nbsp;Japan(树状数组)
- poj 2352 Stars(简单树状数组)此题也可以用线段树来做
- POJ 3468 A Simple Problem with Integers (树状数组写法)
- POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)
- poj 3468 树状数组解法(解决区间更新,区间求和)
- POJ 3468 A Simple Problem with Integers 树状数组 区间修改 区间查询
- POJ--线段树成段更新--树状数组做法
- POJ 2182 Lost Cows (树状数组 or 线段树)
- 树状数组 poj 2352 Stars
- poj 2828 -- Buy Tickets ( 线段树 / 树状数组 )