窝就是喜欢分块!!!

首先,为了凑字数,我先把题面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.

输入输出样例

输入样例#1:

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

输出样例#1:

6
3
0

首先,这道题有无数英雄豪杰用ST表过去了

然后,这道题的tag是树状数组,然而我却不会用树状数组A这道题QAQ

所以,用ST表跑过去之后,我就码了一个分块

分块赛高!!!

好了,我先放code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#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<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#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 ;
}

完结散花!!!