首先,为了凑字数,我先把题面copy过来
我的题库:https://blog.csdn.net/L_Y_T020321/article/details/83152606
我就不copy英文题面了QwQ
每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连续的牛来进行比赛. 但是为了避免水平悬殊,牛的身高不应该相差太大. John 准备了Q (1 <= Q <= 180,000) 个可能的牛的选择和所有牛的身高 (1 <= 身高 <= 1,000,000). 他想知道每一组里面最高和最低的牛的身高差别.
第1行:N,Q
第2到N+1行:每头牛的身高
第N+2到N+Q+1行:两个整数A和B,表示从A到B的所有牛。(1<=A<=B<=N)
输出每行一个数,为最大数与最小数的差
一个农夫有N头牛,每头牛的高度不同,我们需要找出最高的牛和最低的牛的高度差。
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 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.
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.
6 3
1
7
3
4
2
5
1 5
4 6
2 2
6
3
0
首先,这道题有无数英雄豪杰用ST表过去了
然后,这道题的tag是树状数组,然而我却不会用树状数组A这道题QAQ
所以,用ST表跑过去之后,我就码了一个分块
分块赛高!!!
好了,我先放code
#include
#include
#include
#include
#include
#define maxn 100000
using namespace std ;
int tag_max[maxn] , tag_min[maxn] ;//记录块内最大最小
int n , m , a[maxn] ;
int N , pos[maxn] ;//块数以及块
int l[maxn] , r[maxn] ;//刚从别的地方学到的新技能--偷懒
int query_max(int x , int y ) {//区间求最大值
int ans = -1000 ;
if(pos[x] == pos[y]) {
for(int i = x ; i <= y ; i ++) ans = max(ans , a[i]) ;//暴力
}else {
for(int i = x ; i <= r[pos[x]] ; i ++ ) ans = max(ans,a[i]) ;//左边
for(int i = l[pos[y]] ; i <= y ; i ++) ans = max(ans ,a[i]) ;//右边
for(int i = pos[x] + 1 ; i <= pos[y] - 1 ; i ++) ans = max(ans,tag_max[i]) ;//中间
}
return ans ;
}
int query_min(int x , int y ) {//区间求最小值
int ans = 0x7ffffff ;
if(pos[x] == pos[y]) {
for(int i = x ; i <= y ; i ++) ans = min(ans , a[i]) ;
}else {
for(int i = x ; i <= r[pos[x]] ; i ++ ) ans = min(ans,a[i]) ;
for(int i = l[pos[y]] ; i <= y ; i ++) ans = min(ans ,a[i]) ;
for(int i = pos[x] + 1 ; i <= pos[y] - 1 ; i ++) ans = min(ans,tag_min[i]) ;
}
return ans ;
}
int main() {
memset(tag_min,0x3f,sizeof(tag_min)) ;
memset(tag_max,-1,sizeof(tag_max)) ;
scanf("%d%d",&n,&m) ;N = sqrt(n) ;
for(int i = 1 ; i <= n ; i ++) {
pos[i] = (i-1)/N + 1 ;
}
for(int i = 1 ; i <= n ; i ++) l[i] = (i-1) * N + 1 , r[i] = i * N ;
for(int i = 1 ; i <= n ; i ++) {
scanf("%d",&a[i]) ;
tag_max[pos[i]] = max(tag_max[pos[i]],a[i]) ;
tag_min[pos[i]] = min(tag_min[pos[i]],a[i]) ;
}
for(int i = 1 ; i <= m ; i ++) {
int x , y ;
scanf("%d%d",&x,&y) ;
cout << query_max(x,y) - query_min(x,y) << endl ;
}
return 0 ;
}
本人的写法比较笨拙,是用两个query函数分别找出最大值和最小值来相减
当然,我萌也可以选择放到一个函数里
顺手把ST表的写法放上
#include
#include
#include
#include
#define maxn 100010
using namespace std ;
int f_max[maxn][40] , a , x , lc , n , m , p , len , l , r ;
int f_min[maxn][40] ;
int query_max(int l , int r) {
}
int main(){
scanf("%d%d",&n,&m) ;
for(int i = 1 ; i <= n ; i ++){
scanf("%d",&a) ;
f_max[i][0] = a ;
f_min[i][0] = a ;
}
lc = 1ll*(log(n)/log(2)) ;
for(int j = 1 ; j <= lc ; j ++)
for(int i = 1 ; i <= n - (1 << j) + 1 ; i ++)
f_max[i][j] = max(f_max[i][j-1] , f_max[i+(1<<(j-1))][j-1]) ,
f_min[i][j] = min(f_min[i][j-1] , f_min[i+(1<<(j-1))][j-1]) ;
for(int i = 1 ; i <= m ; i ++){
int x , y ;
scanf("%d%d",&l,&r) ;
p = 1ll*(log(r-l+1)/log(2)) ;
x = max(f_max[l][p],f_max[r-(1<<p)+1][p]) ;
y = min(f_min[l][p],f_min[r-(1<<p)+1][p]) ;
cout << x - y <<endl ;
}
return 0 ;
}
完结散花!!!