线段树相关
来源:互联网 发布:mac免费软件 编辑:程序博客网 时间:2024/06/18 06:46
这篇博文讲解的很详细,推荐:http://blog.csdn.net/zearot/article/details/48299459
HDU 1166,单点更新,区间求和
顺便说一下:把输入的字符串定义成string类型的,就会各种超时。不知道是为什么。。。
这里粘贴一下线段树单点更新的模板
#include<bits/stdc++.h>using namespace std;const int N = 50005;int num[N];int Seg[N<<2]; //应该为原数组的4倍大小//平衡二叉树中每个点存储的信息,本题为“和”void PushUp(int iNode) { Seg[iNode] = Seg[iNode*2] + Seg[iNode*2+1];}//原始数据区间[l, r], 当前点为第iNode个点(iNode每次从1开始,根节点)void Build(int l, int r, int iNode) { if(l == r) { Seg[iNode] = num[l]; return; } int m = l + (r-l) / 2; Build(l, m, iNode*2); Build(m+1, r, iNode*2+1); PushUp(iNode);}//原始数据区间[l, r], 在第k个点添加add,当前点为第iNode个点(iNode每次从1开始,根节点)void Update(int k, int add, int l, int r, int iNode) { if(l == r) { Seg[iNode] += add; return; } int m = l + (r-l) / 2; if (k <= m) { Update(k, add, l, m, iNode*2); } else { Update(k, add, m+1, r, iNode*2+1); } PushUp(iNode);}//原始数据区间[l, r](通常为[1, n],表示n个节点),当前查找的区间为[L, R],节点为iNodeint Query(int L, int R, int l, int r, int iNode) { if (L<= l && r <=R) { return Seg[iNode]; } int m = l + (r-l) / 2; int sum = 0; if (L <= m) { sum += Query(L, R, l, m, iNode *2); } if (R > m) { sum += Query(L, R, m+1, r, iNode*2+1); } return sum;}int main() { int t, n, a, b; char str[50]; cin>>t; for(int j = 1; j <= t; j++) { cin>>n; for(int j = 1; j <= n; j++) { scanf("%d",&num[j]); } Build(1,n,1); printf("Case %d:\n",j); while(cin>>str) { if(!strcmp(str,"End")) { break; } if(!strcmp(str,"Add")) { scanf("%d%d",&a,&b); Update(a,b,1,n,1); } if(!strcmp(str,"Sub")) { scanf("%d%d",&a,&b); Update(a,-b,1,n,1); } if(!strcmp(str,"Query")) { scanf("%d%d",&a,&b); int ans=Query(a,b,1,n,1); printf("%d\n",ans); } } } // system("pause"); return 0;}
HDU 1698,区间更新,区间求和
附上模板代码(注:其实此题没有必要做Query操作,直接返回Seg[1]就行了,只是想实现下)
#include<bits/stdc++.h>using namespace std;const int N = 100010;int Seg[N<<2];int isAdd[N<<2]; //标记节点,用于延迟标记.标记的含义:本节点的统计信息已经根据标记更新过了,但是本节点的子节点仍需要进行更新。void PushUp(int iNode) { Seg[iNode] = Seg[iNode*2] + Seg[iNode*2+1];}void Build(int l, int r, int iNode) { if(l == r) { Seg[iNode] = 1; return; } int m = l + (r-l) / 2; Build(l, m, iNode*2); Build(m+1, r, iNode*2 + 1); PushUp(iNode);}//iNode为当前节点,lCnt为当前节点左子树中叶子节点数量,rCnt对应右子树void PushDown(int iNode, int lCnt, int rCnt) { if(isAdd[iNode]) { //下推标记 isAdd[iNode * 2] = isAdd[iNode]; isAdd[iNode*2+1] = isAdd[iNode]; //修改子节点的Seg Seg[iNode * 2] = (lCnt * isAdd[iNode]); Seg[iNode * 2 + 1] = (rCnt * isAdd[iNode]); //清楚本节点标记 isAdd[iNode] = 0; }}//更新[L, R]区间的值为zvoid Update(int L, int R, int z, int l, int r, int iNode) { if (L<=l && r<=R) { Seg[iNode] = (r-l+1)*z; isAdd[iNode] = z; return; } int m = l + (r-l)/2; PushDown(iNode, m-l+1, r-m); if(L <= m) { Update(L, R, z, l, m, iNode*2); } if(R > m) { Update(L, R, z, m+1, r, iNode*2+1); } PushUp(iNode);}int Query(int L, int R, int l, int r, int iNode) { if(L <= l && r <= R) { return Seg[iNode]; } int m = l + (r-l) / 2; PushDown(iNode, m-l+1, r-m); //延迟标记的关键之处?在查询的时候继续向下标记 int sum = 0; if(L<=m) { sum += Query(L, R, l, m, iNode*2); } if(R> m) { sum += Query(L, R, m+1, r, iNode*2+1); } return sum;}int main() { int t; cin >> t; for(int i = 1; i <= t; i++) { int n; cin>> n; memset(isAdd, 0, sizeof(isAdd)); Build(1, n, 1); int q; cin>>q; int x, y, z; while(q--) { //cin >>x >> y >> z; scanf("%d%d%d", &x, &y, &z); Update(x, y, z, 1, n, 1); } cout<< "Case " <<i << ": The total value of the hook is " << Query(1, n, 1, n, 1) <<"."<<endl; } return 0;}
阅读全文
0 0
- 线段树相关问题
- 线段树相关
- 线段树相关
- 【线段树】线段树及其相关 复习
- [线段树] BZOJ 4821 [Sdoi2017]相关分析
- [BZOJ4821][SDOI2017]相关分析(线段树)
- [BZOJ]4821: [Sdoi2017]相关分析 线段树
- bzoj 4821: [Sdoi2017]相关分析 线段树
- 线段树(区间树)及相关应用
- uva 12299 线段树 点相关的操作模板
- opencv 线段相关的函数
- opencv 线段相关的函数
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 利用"线段树"相关算法解决有关数组的问题[待续]
- hdu 4630 No Pain No Game (区间gcd相关x线段树or树状数组)
- RSA算法原理(一)
- 如何在UE4 C++中进行按键绑定
- USACO section 1.3 Combination Lock
- mysql与jsp时间不对应
- shell脚本的简单学习
- 线段树相关
- Android Studio Error:null value in entry: outputDirectory=null编译报错问题
- MyBatis 拦截器(4)
- 键盘钩子
- 两数组的交 II
- hunnu11460—区间求最值(线段树模板)
- java数组创建的三种方式
- BigDecimal精确计算
- Linux IO Scheduler -- Deadline