线段树-基础,典型例题的完整代码
来源:互联网 发布:吕鑫c语言 编辑:程序博客网 时间:2024/05/16 03:04
线段树的应用方法总结
http://www.cnblogs.com/rainydays/p/3671220.html
线段树代码,各类线段树的acm题目学习
http://www.cnblogs.com/Mu-Tou/archive/2011/08/11/2134427.html
HDU 1166 敌兵布阵
题目地址
http://acm.hdu.edu.cn/showproblem.php?pid=1166
例子图
sum[]数组大小是原来大小的4倍
类似堆,数组下标的左右孩子是 i*2 ,i*2 +1(i从1开始)
如上
- sum[1] 存储了 1-10区间的和
- sum[2] 存储了区间[1-5]区间的和
- sum[16] 存储区间[1-1]区间的和,也就是原数组第一个值
ac代码
#include <cstdio>#include <cstdlib>const int N = 50005;int sum[N * 4];void PushUP(int rt) { sum[rt] = sum[2*rt] + sum[2*rt+1]; // 根 等于左孩子值加上右孩子值}void build(int rt, int left, int right) { if (left == right) { scanf("%d", &sum[rt]); return; } int mid = (right - left) / 2 + left; build(2*rt, left, mid); build( 2*rt + 1, mid + 1, right); PushUP(rt);}int query(int qL, int qR, int rt, int left, int right){ if (qL <= left && qR >= right) //查询区间比拥有的区间长,返回根节点 return sum[rt]; int ans = 0; int mid = (right - left) / 2 + left; if (qL <= mid) ans += query(qL, qR, rt * 2, left, mid); //可能 与左区间有交集 if (qR > mid) ans += query(qL, qR, rt * 2 + 1, mid + 1, right); //可能 与右区间有交集 return ans;}// 更新left-right中的某个点,需要递归更新这棵树void update(int pos, int num, int rt, int left, int right){ if (left == right) // 此时有 left == right == pos { sum[rt] += num; return; } int mid = (right - left) / 2 + left; if (pos <= mid) update(pos, num, rt * 2, left, mid); else update(pos, num, rt * 2 + 1, mid + 1, right); PushUP(rt); // 这里注意要新节点的值}int main(){ //freopen("in.txt", "r", stdin); int T, n; scanf("%d", &T); for (int cas = 1; cas <= T; cas++) { printf("Case %d:\n", cas); scanf("%d", &n); build(1, 1, n); char op[10]; while (scanf("%s", op)) { if (op[0] == 'E') break; int a, b; scanf("%d%d", &a, &b); if (op[0] == 'Q') printf("%d\n", query(a, b, 1, 1 ,n)); else if (op[0] == 'S') update(a, -b, 1, 1, n); else update(a, b, 1, 1, n); } } return 0;}
2016 华为编程题
题目描述
老师想知道从某某同学当中,分数最高的是多少,现在请你编程模拟老师的询问。当然,老师有时候需要更新某位同学的成绩.
输入描述:
输入包括多组测试数据。
每组输入第一行是两个正整数N和M(0 < N <= 30000,0 < M < 5000),分别代表学生的数目和操作的数目。
学生ID编号从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩
接下来又M行,每一行有一个字符C(只取‘Q’或‘U’),和两个正整数A,B,当C为’Q’的时候, 表示这是一条询问操作,他询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少
当C为‘U’的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
输出描述:
对于每一次询问操作,在一行里面输出最高成绩.
输入例子:
5 71 2 3 4 5Q 1 5U 3 6Q 3 4Q 4 5U 4 5U 2 9Q 1 5
输出例子:
5659
https://www.nowcoder.com/practice/3897c2bcc87943ed98d8e0b9e18c4666?tpId=49&tqId=29275&tPage=1&rp=1&ru=/ta/2016test&qru=/ta/2016test/question-ranking
线段树ac
#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <string>#include <vector>#include <queue>#include <algorithm>#include <sstream>#include <list>#include <stack> #include <map> #include <set> #include <iterator> using namespace std;const int INF = 0x7fffffff; // 2 147 483 647const int MIN_INF = - INF - 1; // -2 147 483 648const int N = 30005;int n;int m;int init[N];int maxs[N*4];void PushUP(int rt) { maxs[rt] = max(maxs[2*rt], maxs[2*rt+1]);}void build(int rt, int left, int right) { if (left == right) { maxs[rt] = init[left]; //这里赋值注意 return; } int mid = (right - left) / 2 + left; build(2*rt, left, mid); build( 2*rt + 1, mid + 1, right); PushUP(rt);}int query(int qL, int qR, int rt, int left, int right){ if (qL <= left && qR >= right) //查询区间比拥有的区间长,返回根节点 return maxs[rt]; int ans = 0; int mid = (right - left) / 2 + left; if (qL <= mid) ans = max(ans, query(qL, qR, rt * 2, left, mid)); //可能 与左区间有交集 if (qR > mid) ans = max(ans, query(qL, qR, rt * 2 + 1, mid + 1, right)); //可能 与右区间有交集 return ans;}// 更新left-right中的某个点,需要递归更新这棵树void update(int id, int num, int rt, int left, int right){ if (left == right) // 此时有 left == right == id { maxs[rt] = num; return; } int mid = (right - left) / 2 + left; if (id <= mid) update(id, num, rt * 2, left, mid); else update(id, num, rt * 2 + 1, mid + 1, right); PushUP(rt); // 这里注意要新节点的值}int main(){ int i; while(scanf("%d%d", &n, &m) != EOF) { for(i=1;i<=n;i++) { scanf("%d", &init[i]); } build(1, 1, n); for(i=0;i<m;i++) { char c; int a; int b; getchar(); scanf("%c %d %d", &c, &a, &b); if(c == 'Q') { if(a > b){ int tmp = a; a = b; b = tmp; } int val = query(a, b, 1, 1, n); printf("%d\n", val); }else{ update(a, b, 1, 1, n); } } } return 0;}
- 线段树-基础,典型例题的完整代码
- 线段树典型例题--poj2482
- 线段树典型例题--poj2528
- 线段树典型例题--poj2828
- 线段树典型例题--poj3277
- 线段树典型例题--poj2777
- 线段树典型例题--poj3667 hotel
- 二叉树的几道典型例题
- 数论的典型例题
- 动态规划的典型例题
- C#基础入门典型例题(1)
- C#基础入门典型例题(2)
- C#基础入门典型例题(3)
- 典型例题
- 【例题】【线段树】
- 【例题】【线段树】lazy
- 线段树例题5
- 线段树例题集合
- Ubuntu 14.04快速安装ycm
- npm安装包安装时出现的问题
- ThinkPHP3.1.3配置项目
- 求解最长单调子序列.
- 文章标题
- 线段树-基础,典型例题的完整代码
- 文章标题
- 给自己定个小目标:每天写点东西
- 设计模式之-装饰模式
- Android 中AppCompatActivity和Activity中隐藏标题栏的方式
- Qt使用QGraphicsView实现滑动窗体效果
- 文章标题
- Yii2.0 路由
- vim gcc gdb make的使用