线段树和rmq
来源:互联网 发布:衢州软件开发 编辑:程序博客网 时间:2024/05/28 18:44
An easy problem A
N个数排成一列,Q个询问,每次询问一段区间内的数的极差是多少。
Input
第一行两个整数N(1≤N≤50000),Q(1≤Q≤200000)。接下来一行N个整数a1 a2 a3 ….an,(1≤ai≤1000000000)。接下来Q行,每行两个整数L,R(1≤L≤R≤N)。
Output
对于每个询问输出一行,一个整数表示区间内的极差。
Sample Input
5 33 2 7 9 101 52 33 5
Sample Output
853
rmq算法
#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int N = 5e4 + 5;int dp[N][20][2], a[N];int power[20];int main(){ int n, q; for (int i = 0; i < 20; i++) power[i] = 1 << i; while (scanf("%d%d", &n, &q) != EOF) { for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= n; i++) dp[i][0][0] = dp[i][0][1] = a[i]; for (int j = 1; (1 << j) <= n; j++) for (int i = 1; i <= n; i++) if(i+power[j-1]<=n){ dp[i][j][0] = max(dp[i][j - 1][0], dp[i + power[j - 1]][j - 1][0]); dp[i][j][1] = min(dp[i][j - 1][1], dp[i + power[j - 1]][j - 1][1]); } for (int i = 1; i <= q; i++) { int l, r,len; scanf("%d%d", &l, &r); len = (int)(log(r - l + 1) / log(2)); int maxx = max(dp[l][len][0], dp[r - power[len]+1][len][0]);// int minn = min(dp[l][len][1], dp[r - power[len]+1][len][1]); //printf("%d %d\n",maxx,minn); printf("%d\n", maxx-minn); } } return 0;}
查询区间的最大值时从区间两头找,效率非常高,递归也可以实现,但是效率不是很高
线段树
#include<cstdio>#include<algorithm>using namespace std;const int maxn = 5e4 + 5;struct node { int l, r, minn, maxx;}tree[4*maxn];int n, q;void pushup(int rt){ tree[rt].maxx = max(tree[rt << 1].maxx, tree[rt << 1 | 1].maxx); tree[rt].minn = min(tree[rt << 1].minn, tree[rt << 1 | 1].minn);}void build(int l, int r, int rt){ tree[rt].l = l, tree[rt].r = r; if (l == r) { scanf("%d",&tree[rt].maxx); tree[rt].minn = tree[rt].maxx; return; } int mid = r + l >> 1; build(l, mid, rt<<1); build(mid + 1,r, rt << 1 | 1); pushup(rt);}int querymax(int l,int r,int rt){ if (l == tree[rt].l&&r == tree[rt].r) return tree[rt].maxx; int mid = tree[rt].l + tree[rt].r >> 1; if (r <= mid) return querymax(l, r, rt << 1); else if (l > mid) return querymax(l, r, rt << 1 | 1); else return max(querymax(l,mid,rt<<1),querymax(mid+1,r,rt<<1|1));}int querymin(int l, int r, int rt){ if (l == tree[rt].l&&r == tree[rt].r) return tree[rt].minn; int mid = tree[rt].l + tree[rt].r >> 1; if (r <= mid) return querymin(l, r, rt << 1); else if (l > mid) return querymin(l, r, rt << 1 | 1); else return min(querymin(l, mid, rt << 1), querymin(mid + 1, r, rt << 1 | 1));}int main(){ while (scanf("%d%d", &n, &q) != EOF) { build(1, n, 1); for (int i = 1; i <= q; i++) { int a, b; scanf("%d%d",&a,&b); //printf("%d %d\n",querymax(a,b,1),querymin(a,b,1)); int ans = querymax(a, b, 1) - querymin(a, b, 1); printf("%d\n",ans); } } return 0;}
单独查询区间内的极值还是使用rmq快的多。但是线段树的应用更多,可以处理区间值变化的问题
阅读全文
0 0
- 线段树和rmq
- 线段树和RMQ解析和模板
- poj3368(线段树,RMQ)
- 线段树/RMQ问题
- 线段树RMQ
- VJ16216/RMQ/线段树
- 线段树求RMQ
- 线段树 Circular RMQ
- POJ 3368.Frequent values(RMQ和线段树)
- RMQ的两种实现ST算法,和线段树
- sicily 1800 线段树RMQ
- RMQ(线段树实现)
- 线段树 C. Circular RMQ
- Sum up--RMQ--线段树
- 单点更新线段树 RMQ
- POJ 2823 线段树,RMQ
- RMQ线段树(poj3264)
- 士兵杀敌-线段树||RMQ
- 集成学习之AdaBoost
- 互联网小段子——我们一点都不无聊
- AndroidStudio真机测试debug
- maven的依赖与继承
- android studio更新之后打包遇到V1(Jar Signature)、 V2(Full APK Signature)问题
- 线段树和rmq
- Git的简单使用教程
- Linux查看CPU和内存使用状况
- 2,Swift 学习笔记懒加载控件
- IMX6Q下tlv320aic3x音频驱动移植
- IDA权威指南阅读笔记2
- Python Linux上安装MYSQLdb
- Cocoa与Cocoa Touch区别
- 使用tomcat产生的java.lang.ClassNotFoundException: com.mysql.jdbc.Driver问题