倍增思想到ST表RMQ

Balanced Lineup

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 36864   Accepted: 17263
Case Time Limit: 2000MS

Description

For the daily milking, Farmer John‘s N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.

Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.

Input

Line 1: Two space-separated integers, N and Q.
Lines 2..N+1: Line i+1 contains a single integer that is the height of cow i
Lines N+2..N+Q+1: Two integers A and B (1 ≤ ABN), representing the range of cows from A to B inclusive.

Output

Lines 1..Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0
 1 /*
 2 ST表:倍增算法的思想。倍增算法的思想也包含动态规划的思想
 3 O(nlogn)预处理出数组  st[i][j]
 4 代表从s[i]出发的连续2^j个元素中的最值
 5 */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <cmath>
10 #include <algorithm>
11 #include <string>
12 #include <vector>
13 #include <stack>
14 #include <queue>
15 #include <set>
16 #include <map>
17 #include <iomanip>
18 #include <cstdlib>
19 using namespace std;
20 const int INF=0x5fffffff;
21 const double EXP=1e-8;
22 const int MS=50005;
23 int a[MS];
24 int st[MS][20];
25 int st2[MS][20];
26 int prelog2[MS];
27 int N,Q;
28
29 void st_init()
30 {
31     prelog2[1]=0;
32     for(int i=2;i<MS;i++)
33     {
34         prelog2[i]=prelog2[i-1];
35         if((1<<(prelog2[i]+1))==i)
36             ++prelog2[i];
37     }
38     for(int i=N-1;i>=0;i--)
39     {
40         st[i][0]=a[i];
41         st2[i][0]=a[i];
42         for(int j=1;(i+(1<<j)-1)<N;j++)
43         {
44             st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
45             st2[i][j]=max(st2[i][j-1],st2[i+(1<<(j-1))][j-1]);
46         }
47     }
48 }
49 int query_min(int l,int r)
50 {
51     int k=prelog2[r-l+1];
52     return min(st[l][k],st[r-(1<<k)+1][k]);
53 }
54
55 int query_max(int l,int r)
56 {
57     int k=prelog2[r-l+1];
58     return max(st2[l][k],st2[r-(1<<k)+1][k]);
59 }
60
61 int main()
62 {
63     int l,r;
64     scanf("%d%d",&N,&Q);
65     for(int i=0;i<N;i++)
66     {
67         scanf("%d",&a[i]);
68     }
69     st_init();
70     while(Q--)
71     {
72         scanf("%d%d",&l,&r);
73         l--;
74         r--;
75         int max_v=query_max(l,r);
76         int min_v=query_min(l,r);
77         printf("%d\n",max_v-min_v);
78     }
79     return 0;
80 }
时间: 2024-10-05 23:57:27

倍增思想到ST表RMQ的相关文章

K-th occurrence(后缀树组+划分树+ST表+RMQ+二分)

2019CCPC网络选拔赛1003 HDU6704 题目大意: T个测试样例.一个长度为N的字符串S,之后Q个[l,r,k],表示一个子串S[l,r],求出第k个该子串的下标.起始坐标为1.不存在输出-1. 数据范围:1≤T≤20,  1≤N≤105,  1≤Q≤105,  1≤l≤r≤N,  1≤k≤N,  |S|=N; 赛后补题.参考题解说后缀树组+划分树+ST表+二分. 比赛的时候只会后缀树组不会划分树,赛后仔细想,觉得后缀数组可以,然而并不,会TLE. 补提的时候先是采用后缀树组+划分树

ST表(RMQ) 总结

f[i][j] 表示 以i号点为起点 的长度为 2^j 次方 终点为i+2^j-1 的最大或者最小值 打表时间复杂度 O(Nlog2(N)) 查询O(1) 打表代码: for(int i=1;i<=n;i++) { scanf("%d",&f[i][0]); } for(int j=1;j<=log2(n);j++) { for(int i=1;i+(1<<j)-1<=n;i++) { f[i][j]=max(f[i][(j-1)],f[i+(1&

cf689d ST表RMQ+二分

类似hdu5289,但是二分更复杂.本题枚举左端点,右端点是一个区间,需要二分找到区间的左端点和右端点(自己手动模拟一次),然后区间长度就是结果增加的次数 另外结果开long long 保存 /** 二分法,枚举左端点,向右寻找第一个最大值不等于最小值的端点 */ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> us

hdu6107 倍增法st表

发现lca的倍增解法和st表差不多..原理都是一样的 /* 整篇文章分成两部分,中间没有图片的部分,中间有图片的部分 分别用ST表求f1,f2表示以第i个单词开始,连续1<<j行能写多少单词 */ #include<bits/stdc++.h> #define FIN freopen("in.txt","r",stdin); using namespace std; #define ll long long #define MX 100005

[模板]ST表浅析

ST表,稀疏表,用于求解经典的RMQ问题.即区间最值问题. Problem: 给定n个数和q个询问,对于给定的每个询问有l,r,求区间[l,r]的最大值.. Solution: 主要思想是倍增和区间dp. 状态:dp[i][j] 为闭区间[i,i+2^j-1]的最值. 这个状态与转移方程的关系很大,即闭区间的范围涉及到了转移方程的简便性. 转移方程:dp[i][j]=max(dp[i][j-1],dp[i+2^(j-1)][j-1]). 这是显然的,但这里有个细节:第一个项的范围为[i,i+2^

【BZOJ-4569】萌萌哒 ST表 + 并查集

4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 459  Solved: 209[Submit][Status][Discuss] Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2...Sr1与Sl2Sl2+1Sl2+2.

CSU-2221 假装是区间众数(ST表模版题)

题目链接 题目 Description 给定一个非递减数列Ai,你只需要支持一个操作:求一段区间内出现最多的数字的出现次数. Input 第一行两个整数N,Q 接下来一行有N个整数,表示这个序列. 接下来Q行每行一个操作:A B,询问A到B之间出现最多的数字. 1<=N,Q<=100000.-100000<=Ai<=100000 Output 每组数据若干行,每行对应一个询问的答案. Sample Input 10 3 -1 -1 1 1 1 1 3 10 10 10 2 3 1

【倍增】RMQ的ST表算法

RMQ问题:给定一个长度为N的区间,M个询问,每次询问Li到Ri这段区间元素的最大值/最小值. RMQ的高级写法一般有两种,即为线段树和ST表. 本文主要讲解一下ST表的写法.(以区间最大值为例) ST表:一种利用dp求解区间最值的倍增算法. 定义:f[i][j]表示i到i+2^j-1这段区间的最大值. 预处理:f[i][0]=a[i].即i到i区间的最大值就是a[i]. 状态转移:将f[i][j]平均分成两段,一段为f[i][j-1],另一段为f[i+2^(j-1)][j-1]. 两段的长度均

RMQ ST表

//ST表 //计算RMQ 即区间最值 //思想:区间dp+倍增 //注:将代码内所有max改成min即可求最小值 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; int n,m,l,r,a[100001]; int Pow[3