zkw线段树分析
2016-03-20 21:46
127 查看
具体内容见 ppt《统计的力量》
我目前能解决的问题有
1.单点更新+区间求和/求最值
2.区间加减一个数+区间求最值
前缀和的前缀和无思路
1.单点更新+区间求和/求最值
注意此实现在存储的时候从 M+1 开始存
即对于下图 分别从5和9开始存储到6和14 另说明了zkw线段树在存储上是堆的结构
![](http://img.blog.csdn.net/20160320213044247)
代码以hdu1754为例
2.区间加减一个数+区间求最值
即利用差分思路
维护这样一种树
例如 a是b,c的父节点 那么 a = max(b,c);b -= a; c-=a;
上面是求最大值 求最小值改成min即可
以3 9 5 8为例
[图片]
求max的源码 min与之类似
我目前能解决的问题有
1.单点更新+区间求和/求最值
2.区间加减一个数+区间求最值
前缀和的前缀和无思路
1.单点更新+区间求和/求最值
注意此实现在存储的时候从 M+1 开始存
即对于下图 分别从5和9开始存储到6和14 另说明了zkw线段树在存储上是堆的结构
代码以hdu1754为例
#include <iostream> #include <algorithm> #include <cmath> #include <cstdio> #include <cstring> using namespace std; const int maxn = 200000; int T[maxn<<2]; int M; #define PUSHUP(x) T[x] = max(T[x+x],T[x+x+1]) void build_tree(int n) { for(M=1;M <= n+1;M<<=1); memset(T,0,sizeof(int) * (M+M)); for(int i = 1;i<=n;i++) scanf("%d",T+i+M); for(int i = (M+n)/2;i;i--) PUSHUP(i); } int query_tree(int s,int t) { int ans = 0; for(s = s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1) { if(~s&1) ans = max(ans,T[s^1]); if(t&1) ans = max(ans,T[t^1]); } return ans; } void fix_tree(int p,int v) { for(T[p+=M]=v,p>>=1;p;p>>=1) PUSHUP(p); } int main() { int n,m,a,b; char op[5]; while(~scanf("%d%d",&n,&m)) { build_tree(n); while(m--) { scanf("%s%d%d",op,&a,&b); if(op[0]=='Q')printf("%d\n",query_tree(a,b)); else fix_tree(a,b); } } }
2.区间加减一个数+区间求最值
即利用差分思路
维护这样一种树
例如 a是b,c的父节点 那么 a = max(b,c);b -= a; c-=a;
上面是求最大值 求最小值改成min即可
以3 9 5 8为例
[图片]
求max的源码 min与之类似
#include <iostream> #include <cmath> #include <algorithm> #include <cstring> #include <cstdio> using namespace std; const int maxn = 200000; int T[maxn<<2]; int M; void build_tree(int n) { for(M=1;M<=n+1;M<<=1); memset(T,0,sizeof(int)*(M+M)); for(int i = 1;i<=n;i++) scanf("%d",T+i+M); int A; for(int i = (n+M)/2;i;i--) { A = max(T[i+i],T[i+i+1]);T[i+i] -= A;T[i+i+1] -=A;T[i] += A; } } int query_tree(int s,int t) { int Lans=0,Rans=0,ans=0; for(s=s+M,t=t+M;s^t^1;s>>=1,t>>=1) { Lans += T[s]; Rans += T[t]; if(~s&1)Lans = max(Lans,T[s^1]); if(t&1) Rans = max(Rans,T[t^1]); } ans = max(Lans,Rans); while(s>1)ans += T[s>>=1]; return ans; } void fix_tree(int s,int t,int x) { int A; for(s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1) { if(~s&1) T[s^1]+=x; if(t&1) T[t^1]+=x; A = max(T[s],T[s^1]);T[s]-=A;T[s^1]-=A;T[s>>1]+=A; A = max(T[t],T[t^1]);T[t]-=A;T[t^1]-=A;T[t>>1]+=A; } for(;s>1;s>>=1) { A = max(T[s],T[s^1]);T[s]-=A;T[s^1]-=A;T[s>>1]+=A; } } int main() { int n; cin >> n; build_tree(n); // for(int i = 0;i<=50;i++) // cout << i<<":"<<T[i]<<endl; // cout << query_tree(1,14)<<endl; // fix_tree(2,4,2); // fix_tree(3,5,2); // fix_tree(4,6,2); // cout << query_tree(1,14)<<endl; return 0; }
相关文章推荐
- socket 的通信 视频链接
- 管理指针成员
- 【Chromium中文文档】多进程资源加载
- perl array, scalar and hash
- Android画图工具——Canvas
- 集合-Set
- 读书笔记| (三)ARM9 嵌入式学习:ARM实验篇
- hdu1402A * B Problem Plus
- 英文歌曲:Yesterday Once More(昨日重现)
- 【机房个人重构】数据库设计之物理设计
- 汇编学习3
- SNAT
- webView的使用
- 欢迎使用CSDN-markdown编辑器
- Java - 多线程
- print(),print_r(),echo()的区别
- DOM对象编程练习小结
- Android系统组件BroadcastReceiver
- u插件开发,图解每个js之前的通信
- 整数因子分解