题目链接:这道题是线段树,树状数组最基础的问题

两种分类方式:按照更新对象和查询对象

单点更新,区间查询;

区间更新,单点查询;

按照整体维护的对象:

维护前缀和;

维护区间最值.

线段树模板代码

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define re(i,n) for(int i=0;i<n;i++)
typedef long long ll;
const int maxn = 2 * 1e5 + 7;
#define lson(x) x<<1,f,mid
#define rson(x) x<<1|1,mid+1,t
int n, m;
int tr[maxn << 2];
int x, y;
int ans;
void build(int r, int f, int t){if (f == t){scanf("%d", &tr[r]);return;}int mid = (f + t) >> 1;build(lson(r)),build(rson(r));tr[r] = max(tr[r << 1], tr[r << 1 | 1]);
}
void query(int r, int f, int t){if (f >= x&&t <= y){ans = max(ans, tr[r]);return;}int mid = (f + t) >> 1;if (x <= mid)query(lson(r));if (y > mid)query(rson(r));
}
void update(int r, int f, int t){if (f == t){tr[r] = y;return;}int mid = (f + t) >> 1;if (x<= mid)update(lson(r));else update(rson(r));tr[r] = max(tr[r << 1], tr[r << 1 | 1]);
}
int main(){//freopen("in.txt", "r", stdin);while (cin >> n >> m){ build(1, 1, n); while (m--){char op[2];  scanf("%s%d%d", op,&x,&y); if (op[0] == 'Q'){if (x > y)swap(x, y);ans = -1;query(1, 1, n);printf("%d\n", ans);}else{update(1, 1, n);}}}return 0;
}

树状数组区间最值模板代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 2*1e5+7;
typedef long long ll;
#define re(i,n) for(int i=0;i<n;i++)
int a[maxn], c[maxn];
/*
a里面存放本值,c里面维护最值
*/
int n, q;
int lowbit(int x){return x&-x;
}
void redo(int i){c[i] = i;for (int j = 1; j < lowbit(i); j <<= 1)if (a[c[i - j]]>a[c[i]])c[i] = c[i - j];
}
void init(){for (int i = 1; i <= n; i++){redo(i);}
}
void update(int x, int y){ bool big = y > a[x];a[x] = y;int i = x;if (big){/*这个地方如果错写成a[c[i]]<y就会导致无法传递上去,因为一开始时就是a[c[i]]==y.*/while (i<=n&&a[c[i]] <= y)c[i] = x, i += lowbit(i);}else{ while (i<=n&&c[i] == x)redo(i), i += lowbit(i);}
}
int query(int l, int r){int ans = a[r];while (l<=r){ while (r - lowbit(r) >= l){ans = max(a[c[r]], ans);r -= lowbit(r);}ans = max(a[r], ans);//根节点r--;//向下走一步
    }return ans;
}
int main(){freopen("in.txt", "r", stdin);while (scanf("%d%d", &n, &q) == 2){re(i, n)scanf("%d", &a[i + 1]);init();int qi = 0;while (q--){char op[2]; int x, y;qi++;scanf("%s%d%d", &op, &x, &y);if (op[0] == 'U'){update(x, y);}else{int ans = query(x, y);printf("%d\n", ans);}}}return 0;
}

复杂度是O(lgn*lgn).这道题数据好像有点弱,因为错误的代码也能过这道题.

zwk线段树模板

zwk线段树巧妙之处在于开区间写法,对于长度为N的线段,初始化时,共N+2片叶子:1和N+2空着,2~N+1才是本体,是实实在在的数据.张昆玮说了:如果有1023个数据,那就要有2048片叶子.空间要开到(N+2)*4才行.虽然费了点空间,但编程简洁了.

根节点(1号结点)和每层的第一个节点和最后一个节点是哨兵节点,永远都不会访问到它们.它们的存在只是方便编程.老子曰:将欲取之,必先予之.一言以蔽之,就是两端边界处的节点都是哨兵节点,这是开区间方便编程导致的.

那么闭区间写法行不行呢?对于长度为N的线段,1~N全部用上,查询时闭区间可以转换成开区间.如果有1023个数,那就只需要开辟1024片叶子的树状数组.开区间=闭区间-两个端点.若无论如何都更新两个端点,那就会导致更新的东西有点靠下,这对于结果并没什么影响.需要注意l==r的情形.

zwk开区间写法

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 2 * 1e5 + 7;
 6 typedef long long ll;
 7 #define re(i,n) for(int i=0;i<n;i++)
 8 int a[maxn << 2];
 9 int n, q, sz;
10 void update(int x, int v){
11     x += sz;
12     a[x] = v;
13     while (x >1){
14         x >>= 1;
15         a[x] = max(a[x << 1], a[x << 1 | 1]);
16     }
17 }
18 int query(int l, int r){
19     l += sz - 1, r += sz + 1;
20     int ans =0;
21     while (l^r ^ 1){//当两人不是兄弟时
22         if (~l & 1){
23             ans = max(ans, a[l ^ 1]);
24         }
25         if (r & 1){
26             ans = max(ans, a[r ^ 1]);
27         }
28         l >>= 1, r >>= 1;
29     }
30     return ans;
31 }
32 int main(){
33     //freopen("in.txt", "r", stdin);
34     while (scanf("%d%d", &n, &q) == 2){
35         sz = 1; while (sz < n+2)sz <<= 1;
36         re(i, n){
37             scanf("%d", &a[i + sz+1]);
38         }
39         for (int i = n; i <= (sz << 1); i++)a[i + sz+1] = 0;
40         for (int i = sz - 1; i>0; i--){
41             a[i] = max(a[i << 1], a[i << 1 | 1]);
42         }
43         while (q--){
44             char op[2]; int x, y;
45             scanf("%s%d%d", op, &x, &y);
46             if (op[0] == 'U'){
47                 update(x, y);
48             }
49             else{
50                 int ans = query(x, y);
51                 printf("%d\n", ans);
52             }
53         }
54     }
55     return 0;
56 }

zwk闭区间写法:下面的代码有bug.能过题.

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 2 * 1e5 + 7;
 6 typedef long long ll;
 7 #define re(i,n) for(int i=0;i<n;i++)
 8 int a[maxn << 2];
 9 int n, q, sz;
10 void update(int x, int v){
11     x += sz-1;
12     a[x] = v;
13     while (x >1){
14         x >>= 1;
15         a[x] = max(a[x << 1], a[x << 1 | 1]);
16     }
17 }
18 int query(int l, int r){
19     l += sz - 1, r += sz - 1;
20     int ans =max(a[l],a[r]); //查询时先把两个端点给处理掉,就相当于开区间了.
21     /*
22     这个地方的不同决定了两种写法,我觉得没有必要开区间.闭区间预处理一下就很好.
23     这个地方如果l==r,就会产生死循环.但是我这么写,这道题却过了.*/
24     while (l^r ^ 1){//当两人不是兄弟时
25         if (~l & 1){
26             ans = max(ans, a[l ^ 1]);
27         }
28         if (r & 1){
29             ans = max(ans, a[r ^ 1]);
30         }
31         l >>= 1, r >>= 1;
32     }
33     return ans;
34 }
35 void init(){
36     sz = 1; while (sz < n)sz <<= 1;
37     re(i, n){
38         scanf("%d", &a[i + sz]);//在1~N之间存放数据
39     }
40     for (int i = n; i <= (sz << 1); i++)a[i + sz ] = 0;
41     for (int i = sz - 1; i>0; i--){
42         a[i] = max(a[i << 1], a[i << 1 | 1]);
43     }
44 }
45 int main(){
46     freopen("in.txt", "r", stdin);
47     while (scanf("%d%d", &n, &q) == 2){
48         init();
49         while (q--){
50             char op[2]; int x, y;
51             scanf("%s%d%d", op, &x, &y);
52             if (op[0] == 'U'){
53                 update(x, y);
54             }
55             else{
56                 int ans = query(x, y);
57                 printf("%d\n", ans);
58             }
59         }
60     }
61     return 0;
62 }

转载于:https://www.cnblogs.com/weiyinfu/p/4854396.html

hdu1754 I hate it线段树模板 区间最值查询相关推荐

  1. BZOJ-4811: [Ynoi2017]由乃的OJ (树链剖分 线段树维护区间操作值 好题)

    4811: [Ynoi2017]由乃的OJ Time Limit: 6 Sec  Memory Limit: 256 MB Submit: 366  Solved: 118 [Submit][Stat ...

  2. 【HDU - 1698】 Just a Hook(线段树模板 区间覆盖更新(laz标记) + 区间和查询 )

    题干: In the game of DotA, Pudge's meat hook is actually the most horrible thing for most of the heroe ...

  3. POJ——3624 Balanced Lineup(线段树入门——区间最值问题)

    原题链接:http://poj.org/problem?id=3264 每天挤奶时,农夫John的N头奶牛(1≤N≤50,000头)总是按照相同的顺序排列.一天,农夫约翰决定和几头牛组织一场极限飞盘游 ...

  4. 【POJ - 3468 】 A Simple Problem with Integers (线段树模板 区间更新 + 区间和查询)(不能树状数组或差分数组)

    题干: You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o ...

  5. 【HDU - 3974】 Assign the task (dfs序 + 线段树维护 区间更新+ 单点查询)

    题干: There is a company that has N employees(numbered from 1 to N),every employee in the company has ...

  6. [SCOI2007]降雨量 线段树和区间最值(RMQ)问题

    题目链接P2471 [SCOI2007]降雨量 听说博客观看效果更佳    这道题是比较经典的 RMQRMQRMQ 问题,找到X和Y年间的最值来进行判断真假 , 用线段树维护是比较简单好写的.然而这只 ...

  7. 线段树(区间修改)模板题 Luogu 2357 守墓人

    众所周知,线段树可以在O( log n)的时间内进行很多修改和查询的操作,应用很广. 线段树,顾名思义,是一个二叉树,但是每个节点,存的不是不是"数",而是一个"区间&q ...

  8. 线段树模板题3:区间染色问题

    1.3线段树模板题3:区间染色问题 在DotA游戏中,帕吉的肉钩实际上是大多数英雄中最恐怖的东西.挂钩由长度相同的几个连续的金属棍组成. 现在,帕吉(Pudge)希望对挂接进行一些操作. 让我们将钩子 ...

  9. CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换,清晰易懂)

    CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换)   首先一共有四个操作,第一个和第四个都是线段树的基本操作,直接用线段树实现.      第 ...

最新文章

  1. Excel超级链接方式应用技巧
  2. 44. 源代码解读-RocketMQ-架构
  3. rootfs 制作ubuntu_为n1制作aarcm64/arm64 ubuntu rootfs系统
  4. winCE改变字库方法(WINCE字库更新)
  5. Spring 之注解事务 @Transactional
  6. Intellij IDEA中Mybatis Mapper自动注入警告的6种解决方案
  7. [有限元] Ansys Workbench Mechanical 中的应力应变显示类型的文档翻译
  8. 未来互联网还有哪些值得关注的趋势?
  9. git不能上传空目录和设备文件
  10. adb—fastboot—Download Honor 4C ClockworkMod (Cofface) Custom Recovery
  11. 聚宽数据(JQData)本地化解决方案:基于MongoDB
  12. 这是我见过最好的唐诗,而且通俗易懂2
  13. “心脏滴血”漏洞复现
  14. 基于Huggingface的预训练语言模型分类体系及实战
  15. ios 基于CAEmitterLayer的雪花,烟花,火焰,爱心等效果demo
  16. Latex标题页的上标和脚注
  17. UG CAM 开发获取工序导航器当前选择的操作、程序组、几何体、刀具方法,获得名字并修改名字
  18. 华为鸿蒙os尝鲜,华为鸿蒙os尝鲜版
  19. 跨境电商「独角兽」融资40亿+,这家公司是怎么做增长的?
  20. c# iot .net 树莓派读取土壤湿度感应器 代码实例

热门文章

  1. [考试反思]0813NOIP模拟测试20
  2. net.sf.json.JSONObject处理 null 字符串的一些坑
  3. angularjs -- 页面模板清除
  4. openstack镜像制作详解
  5. 7.1 XHTML的规范化
  6. Frameset使用教程
  7. [已解决问题] Could not find class XXX referenced from method XXX.YYY
  8. 一步步构建大型网站架构(转载)
  9. java一次性查询几十万,几百万数据解决办法
  10. 免费的中文OCR软件