题目背景

这是一道ST表经典题——静态区间最大值

请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)

题目描述

给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数字的最大值。

输入输出格式

输入格式:

第一行包含两个整数 N,M,分别表示数列的长度和询问的个数。

第二行包含 N 个整数(记为 ai ),依次表示数列的第 i 项。

接下来 M 行,每行包含两个整数 li,ri,表示查询的区间为 [li,ri]

输出格式:

输出包含 M行,每行一个整数,依次表示每一次询问的结果。

输入输出样例

输入样例#1:
复制

  1. 8 8
  2. 9 3 1 7 5 6 0 8
  3. 1 6
  4. 1 5
  5. 2 7
  6. 2 6
  7. 1 8
  8. 4 8
  9. 3 7
  10. 1 8
输出样例#1: 复制

  1. 9
  2. 9
  3. 7
  4. 7
  5. 9
  6. 8
  7. 7
  8. 9

说明

对于30%的数据,满足: 1≤N,M≤10

对于70%的数据,满足: 1≤N,M≤10^5

对于100%的数据,满足: 1≤N≤10^5,1≤M≤10^6,ai∈[0,10^9],1≤li≤ri≤N

题解

这道题在遥远的远古写过ST

  1. /*
  2. qwerta
  3. P3865 【模板】ST表
  4. Accepted
  5. 100
  6. 代码 C++,0.55KB
  7. 提交时间 2018-03-01 16:26:10
  8. 耗时/内存
  9. 1552ms, 9921KB
  10. */
  11. #include<cmath>
  12. #include<cstdio>
  13. #include<iostream>
  14. using namespace std;
  15. int f[][];
  16. int main()
  17. {
  18. int x,y,m,n,i,j;
  19. //scan
  20. scanf("%d%d",&n,&m);
  21. for(i=;i<=n;i++)
  22. scanf("%d",&f[i][]);
  23. //build
  24. for(j=;(<<j)<=n;j++)
  25. for(i=;i+(<<j)-<=n;i++)
  26. f[i][j]=max(f[i][j-],f[i+(<<(j-))][j-]);
  27. //search
  28. for(i=;i<=m;i++)
  29. {
  30. scanf("%d%d",&x,&y);
  31. j=log2(y-x+);
  32. //cout<<x<<" "<<j<<" "<<f[x][j]<<" "<<f[y-(1<<j)+1][j]<<endl;
  33. printf("%d\n",max(f[x][j],f[y-(<<j)+][j]));
  34. }
  35. return ;
  36. }

然后为了测树剖中间的动态区间最值有没有写错(emmm),把那一段粘过来试了一下

预处理nlogn,修改logn

  1. /*
  2. qwerta
  3. P3865 【模板】ST表
  4. Accepted
  5. 100
  6. 代码 C++,1.19KB
  7. 提交时间 2018-09-11 16:07:47
  8. 耗时/内存
  9. 1972ms, 6084KB
  10. */
  11. #include<cstdio>
  12. #include<iostream>
  13. using namespace std;
  14. const int MAXN=1e5+;
  15. struct qaq{
  16. int l,r,v;
  17. }a[*MAXN];
  18. int val[MAXN];
  19. void build(int i,int ll,int rr)
  20. {
  21. a[i].l=ll;
  22. a[i].r=rr;
  23. if(ll==rr){a[i].v=val[ll];return;}
  24. int mid=(ll+rr)>>;
  25. build((i<<),ll,mid);
  26. build(((i<<)|),mid+,rr);
  27. a[i].v=max(a[(i<<)].v,a[((i<<)|)].v);
  28. return;
  29. }
  30. void add(int i,int x,int k)
  31. {
  32. if(a[i].l==a[i].r){a[i].v=k;return;}
  33. int mid=(a[i].l+a[i].r)>>;
  34. if(x<=mid)add((i<<),x,k);
  35. else add(((i<<)|),x,k);
  36. a[i].v=max(a[(i<<)].v,a[((i<<)|)].v);
  37. return;
  38. }
  39. int ans;
  40. void find(int i,int ll,int rr)
  41. {
  42. if(a[i].l==ll&&a[i].r==rr){ans=max(ans,a[i].v);return;}
  43. int mid=(a[i].l+a[i].r)>>;
  44. if(rr<=mid)find((i<<),ll,rr);
  45. else if(mid+<=ll)find(((i<<)|),ll,rr);
  46. else {find((i<<),ll,mid);find(((i<<)|),mid+,rr);}
  47. return;
  48. }
  49. int main()
  50. {
  51. //freopen("a.in","r",stdin);
  52. int n,m;
  53. scanf("%d%d",&n,&m);
  54. for(int i=;i<=n;++i)
  55. scanf("%d",&val[i]);
  56. build(,,n);
  57. for(int i=;i<=m;++i)
  58. {
  59. int l,r;
  60. scanf("%d%d",&l,&r);
  61. ans=;
  62. find(,l,r);
  63. printf("%d\n",ans);
  64. }
  65. return ;
  66. }

根本没有慢多少!

「LuoguP3865」 【模板】ST表 (线段树的更多相关文章

  1. 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径

    51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...

  2. 【LOJ】#3109. 「TJOI2019」甲苯先生的线段树

    LOJ#3109. 「TJOI2019」甲苯先生的线段树 发现如果枚举路径两边的长度的话,如果根节点的值是$x$,左边走了$l$,右边走了$r$ 肯定答案会是$(2^{l + 1} + 2^{r + ...

  3. 51nod 1593 公园晨跑 | ST表(线段树?)思维题

    51nod 1593 公园晨跑 有一只猴子,他生活在一个环形的公园里.有n棵树围绕着公园.第i棵树和第i+1棵树之间的距离是 di ,而第n棵树和第一棵树之间的距离是 dn .第i棵树的高度是 hi ...

  4. Glad You Came hdu-6356(ST表 || 线段树)

    第一种用线段树,用两颗数维护区间最大值和区间的最小值,然后更新的时候如果我目前区间内的最大值比我得到的v小,那么我就把这个区间修改成v,如果我的最小值比v大,那么v就是没有用的,直接跳过,然后这样每次 ...

  5. Codeforces 487B Strip (ST表+线段树维护DP 或 单调队列优化DP)

    题目链接 Strip 题意   把一个数列分成连续的$k$段,要求满足每一段内的元素最大值和最小值的差值不超过$s$, 同时每一段内的元素个数要大于等于$l$, 求$k$的最小值. 考虑$DP$ 设$ ...

  6. bzoj 1699: [Usaco2007 Jan]Balanced Lineup排队【st表||线段树】

    要求区间取min和max,可以用st表或线段树维护 st表 #include<iostream> #include<cstdio> using namespace std; c ...

  7. (DP ST表 线段树)51NOD 1174 区间中最大的数

    给出一个有N个数的序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,最大的数是多少.   例如: 1 7 6 3 1.i = 1, j = 3,对应的数为7 6 3,最大的数为7. ...

  8. [luoguP1816] 忠诚(st表 || 线段树)

    传送门 其实我就是想练练 st表 本以为学了线段树可以省点事不学 st表 了 但是后缀数组中用 st表 貌似很方便 所以还是学了吧,反正也不难 ——代码 #include <cstdio> ...

  9. RMQ--树状数组,ST表,线段树

    RMQ Range Minimum/Maximum Query 区间最值问题 树状数组 https://www.cnblogs.com/xenny/p/9739600.html lowbit(x) x ...

  10. loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

    题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ...

随机推荐

  1. H5页面基于iScroll.js插件实现下拉刷新,上拉加载更多

    前言 在我之前的项目中,页面总是干巴巴的,用户的体验不是特别完美,我也是一直觉得把设计师给到的psd做出来就好,很少考虑用户的感受.我喜欢看不同的App,操作每个步骤,观赏每个能和我互动的交互设计效果 ...

  2. Java普通员工管理系统

    login GUI界面(登录) package 普通员工管理系统; import java.awt.event.ActionEvent; import java.awt.event.ActionLis ...

  3. Ionic 学习笔记

    本文为原创,转载请注明出处: cnzt       文章:cnzt-p http://www.cnblogs.com/zt-blog/p/7831153.html 注: 本篇学习笔记基于Ionic 3 ...

  4. [转] sql 删除表数据的drop、truncate和delete用法

    删除表数据的关键字,大家记得最多的可能就是delete.然而,我们做数据库开发,读取数据库数据.对另外的drop.truncate用得就比较少了. 1 drop 出没场合:drop table  ta ...

  5. Adding an Exception Breakpoint - Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 25 bey

    用如下的方法可以非常方便停留到具体crash的某行代码 Adding an Exception Breakpoint Add an exception breakpoint to your proje ...

  6. android开发教程之使用线程实现视图平滑滚动示例 改

    package com.melonsapp.messenger.ui.popupuser; import android.os.Handler; import android.view.View; i ...

  7. C++类型的转换

    C风格转换是“万能的转换”,但需要程序员把握转换的安全性,编译器无能为力:static_cast最接近于C风格转换,但在无关类指针转换时,编译器会报错,提升了安全性:dynamic_cast要求转换类 ...

  8. ZT:150条毒鸡汤

    1.照照镜子吧,还要什么段子? 2.多年过去,再回忆高考,其实本质上没有考到好与坏的说法,重要的是年轻人在一起,做份试题,然后决定去哪座城市做代购. 3.真正努力过的人,就会明白天赋的重要性. 4.转 ...

  9. HDU 2009 整除的尾数 题解

    Problem Description 一个整数,仅仅知道前几位,不知道末二位.被还有一个整数除尽了.那么该数的末二位该是什么呢?   Input 输入数据有若干组,每组数据包括二个整数a,b(0&l ...

  10. 卸载 linux http

    当我们想卸载httpd 的时候,使用rpm -qa httpd 的时候,我们发现有很多的依赖包.我们耐心的想一个一个的卸载的时候(使用rpm -e httpd-*),还会进入死循环.解决的办法是:使用 ...