树状数组区间修改 neu1454
来源:互联网 发布:php字符串查找 编辑:程序博客网 时间:2024/06/07 05:35
树状数组不止可以单点修改也可以进行区间修改
但是要建立两个树状数组进行维护
第一个树状数组B[i]存储的是 就是i所表示的区间上所有数字都被加了多少。比如B[i]=v,表示i区间上每个数都加上了v。
因为树状数组只能够修改区间1-x,加上v(v可能为负数)
所以第二个树状数组C[i]存储的是区间修改[1-x](x>=i)对于区间i的影响。比如现在修改区间[1-x],如果x<i,那么不对C[i]操作,如果i>=x,那么C[i]+=x*v;
下面是我的模板:
int ADD_B(int x, int v){ for (int i=x; i>0; i-=i&(-i)) B[i]+= v; return 0;}int ADD_C(int x, int v){ for (int i=x; i<=n; i+=i&(-i)) C[i]+=c*x; return 0;}
这里是修改操作。
int SUM_B(int x){ int ans = 0; for (int i=x; i<=n; i+=i&(-i)) s += B[i]; return ans;}int SUM_C(int x){ int ans = 0; for (int i=x; i>0; i-=i&(-i)) ans += C[i]; return ans;}这里是查询操作,但是记住B与C所形成的树状数组都不是很完全,所以还要进行一下操作。
int SUM(int x){ if (x)return SUM_B(x)*x+SUM_C(x-1); return 0;}
至于为什么这样写,对应上面C树状数组与B树状数组的定义。
修改区间[l,r] +v
ADD_B(r,v);ADD_C(r,V);if (l>1) ADD_B(l-1,-v),ADD_C(l-1,-v);
查询区间[l,r]
int ans;if (l>1) ans=SUM(r)-SUM(l-1);else ans=SUM(r);
1454: 逃票的chanming(1
时间限制: 1 Sec 内存限制: 128 MB提交: 402 解决: 15
[提交][状态][讨论版]
题目描述
这是一个神奇的国度。
这个国度一共有N个城市组成,让我们将他们编号为1~N,
这一天,chanming带着他的第一个月的工资K元来到了城市1。他想到城市N去寻找宝藏。qinhang3想跟chanming一起去,但是chanming并不想带他(太大只,逃票太明显)。于是他对qinhang3说,这样吧,你帮我解决这个问题,我们就一起走,不然就只能友尽了,这个题目是这样的:
有一个长度为N的序列,初始值都为0。
现在有2种不同操作:
操作0: 读入p,q,v,并且a[p] ^= v, a[p + 1] ^= v, .. ,a[q] ^= v;
操作1: 读入p,q,输出s = a[p] ^ a[p + 1] ^ a[p + 2]..^a[q]的结果;
*@.@*...还好qinhang3找到了一位神犇帮忙,不用东张西望了,就是你!如果你能解决这个问题的话,qinhang3将送给你一个精美的气球作为报答。
这个国度一共有N个城市组成,让我们将他们编号为1~N,
这一天,chanming带着他的第一个月的工资K元来到了城市1。他想到城市N去寻找宝藏。qinhang3想跟chanming一起去,但是chanming并不想带他(太大只,逃票太明显)。于是他对qinhang3说,这样吧,你帮我解决这个问题,我们就一起走,不然就只能友尽了,这个题目是这样的:
有一个长度为N的序列,初始值都为0。
现在有2种不同操作:
操作0: 读入p,q,v,并且a[p] ^= v, a[p + 1] ^= v, .. ,a[q] ^= v;
操作1: 读入p,q,输出s = a[p] ^ a[p + 1] ^ a[p + 2]..^a[q]的结果;
*@.@*...还好qinhang3找到了一位神犇帮忙,不用东张西望了,就是你!如果你能解决这个问题的话,qinhang3将送给你一个精美的气球作为报答。
输入
单组数据
第一行为两个数N,M,分别表示序列的个数和操作的个数
接下来M行,第一个数op,表示操作的种类,如果为0,读入p,q,v,如果为1,读入p,q
N <= 500000
M <= 500000
0 < v < 2^30
输出
对于每次操作1,输出计算结果。
样例输入
100 30 2 6 30 1 2 71 2 3
样例输出
7
提示
由于涉及大规模输入输出,请使用SCANF与PRINTF来避免TLE..
我的代码:
#include <cstdio>#include <cstring>#include <iostream>using namespace std;int C[500005];int B[500005];int n,m;void ADD_B(int x, int c){ for (int i=x; i>0; i-=i&(-i)) B[i]^= c;}void ADD_C(int x, int c){ for (int i=x; i<=n; i+=i&(-i)) if (x%2) C[i]^=c;}int SUM_B(int x){ int s = 0; for (int i=x; i<=n; i+=i&(-i)) s ^= B[i]; return s;}int SUM_C(int x){ int s = 0; for (int i=x; i>0; i-=i&(-i)) s ^= C[i]; return s;}inline int SUM(int x){ if (x%2) return SUM_B(x)^SUM_C(x - 1); else if (x!=0) return SUM_C(x-1); else return 0;}int main (){ int a,l,r,v; while(scanf("%d%d",&n,&m)==2) { memset(C,0,sizeof(C)); for(int i=0;i<m;i++) { scanf("%d",&a); if(a==0) { scanf("%d%d%d",&l,&r,&v); if (l>1){ ADD_B(l-1,v); ADD_C(l-1,v); } ADD_B(r,v); ADD_C(r,v); } else { scanf("%d%d",&l,&r); int ans=SUM(l-1)^SUM(r); //cout <<sum(l-1)<<endl; //cout <<sum(r)<<endl; printf("%d\n",ans); } } } return 0;}
0 0
- 树状数组区间修改 neu1454
- 树状数组 区间修改
- 树状数组 区间修改查询
- 树状数组区间修改+查询
- poj3468(树状数组:区间修改 区间求和)
- 树状数组~poj3468~区间修改 区间查询
- 树状数组 --区间查询+区间修改
- 【codevs1082】【树状数组】 区间修改 区间查询
- 树状数组 区间修改区间求和总结
- 笔记 树状数组--区间查询+区间修改
- 树状数组实现 区间修改+区间查询
- 树状数组区间修改区间查询
- 树状数组 区间修改+区间查询
- 树状数组区间修改区间查询
- 树状数组 区间修改 区间查询
- 【树状数组】区间修改&点查询
- 【树状数组】点修改&区间查询
- 【树状数组】HUD1556 区间修改单点求值
- ogre部署到vs2010
- Hdu1385 Minimum Transport Cost (disjtra)
- PHP文件下载
- Android开发(准确来说ndk开发)openGL 开启depth_test 没反应
- hdu-oj 1106 排序
- 树状数组区间修改 neu1454
- Hibernate Session & Transaction详解
- sys_connect_by_path
- uva 424 Integer Inquiry (大数加法)
- 计算机网络--NetBIOS
- 腾讯地图实现多点标注
- C++引用传递和值传递
- PHP+FastCGI+Nginx动态请求处理配置
- Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 393216 byt