POJ 3468 A Simple Problem with Integers(树状数组区间更新)
2015-11-07 14:11
423 查看
今天来学习一下怎么用BIT区间更新的,BIT速度比线段树速度更快,也更好写。
我们来看一下当给区间[l,r]整体加上一个常数c会前缀si发生什么变化?
i < l ,si不变; l ≤ i ≤ r,si 增加 了c*(i-l+1); r < i,si 增加了c*(r-l+1)。
如果画出增量与下标的坐标图,我们可以发现两边增加的都是常量,而中间的散点在一条斜率为c的直线上。
因此我们可以用一个斜率和常数的组合来表示前缀和,si = b1 *i + b2。
那么给区间[l,r]加上c可以表示为:
1. [l,r]上每个结点的斜率加上c,b1上l位置加c,r+1位置减c。
2.虽然步骤1更新了[l,r]的斜率,但是增量却往上平移了c*(l-1),因此在b2上l位置减掉c*(l-1)。
3.最后更新r < i之后的常数,在b2上r+1位置加上掉c*(r)。
运行效率对比: 未加I/O挂
BIT 1891ms,线段树(适当维护信息) 2349ms , 线段树(懒操作) 2500ms 。
我们来看一下当给区间[l,r]整体加上一个常数c会前缀si发生什么变化?
i < l ,si不变; l ≤ i ≤ r,si 增加 了c*(i-l+1); r < i,si 增加了c*(r-l+1)。
如果画出增量与下标的坐标图,我们可以发现两边增加的都是常量,而中间的散点在一条斜率为c的直线上。
因此我们可以用一个斜率和常数的组合来表示前缀和,si = b1 *i + b2。
那么给区间[l,r]加上c可以表示为:
1. [l,r]上每个结点的斜率加上c,b1上l位置加c,r+1位置减c。
2.虽然步骤1更新了[l,r]的斜率,但是增量却往上平移了c*(l-1),因此在b2上l位置减掉c*(l-1)。
3.最后更新r < i之后的常数,在b2上r+1位置加上掉c*(r)。
运行效率对比: 未加I/O挂
BIT 1891ms,线段树(适当维护信息) 2349ms , 线段树(懒操作) 2500ms 。
/********************************************************* * ------------------ * * author AbyssalFish * **********************************************************/ #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<queue> #include<vector> #include<stack> #include<vector> #include<map> #include<set> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int maxn = 1e5+1; ll C[2][maxn]; ll psum[maxn]; int N; inline void add(ll C[],int x,int d) { while(x <= N){ C[x] += d; x += x&-x; } } inline ll sum(ll C[],int x) { ll ret = 0; while(x > 0){ ret += C[x]; x &= x-1; } return ret; } inline ll query(int x){ return sum(C[1],x)*x+sum(C[0],x); } //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif int Q; scanf("%d%d",&N,&Q); for(int i = 1; i <= N; i++){ scanf("%I64d", psum + i); psum[i] += psum[i-1]; } char op[2]; while(Q--){ int l,r; scanf("%s%d%d",op,&l,&r); if(*op == 'Q'){ printf("%I64d\n",query(r)-query(l-1)+psum[r]-psum[l-1]); }else { int c; scanf("%d",&c); add(C[1],l,c); add(C[1],r+1,-c); add(C[0],l,c*(1-l)); add(C[0],r+1,c*(r)); } } return 0; }
相关文章推荐
- 从集中式到分布式
- mysql处理中文乱码的问题
- EF 三层 BLL DAL
- GTK+图形化应用程序开发学习笔记(十二)—对话框构件、标尺构件
- 大二训练第一周 G - Keywords Search 艾斯atman
- 正则判断手机号
- 阿里云免费服务器搭建学习过程--成功:
- android-ViewPager实现图片自动切换
- mysql学习笔记(1)
- GTK+图形化应用程序开发学习笔记(十一)—箭头构件、工具提示对象
- Java记录 -63- Java的键值映射Map
- php实现点击可刷新验证码
- iOS调试技巧之打印输出 -----A: (NSString *)description B:自定义LOG C:使用第三方插件快速打印
- 封装
- GTK+图形化应用程序开发学习笔记(十)—工具条
- [C++ Mind Map] class and memory
- 学习笔记
- 如何避免上传gif到数据库时变成静态图片
- HyperlinkButton——WP8控件学习
- mac安装brew