题意: 2.1 给一个长度为n的数组a,和m次查询k,输出m行,每行一个整数,表示第i次查询时所有满足“区间最大值-区间最小值>k”的区间个数。 2.2 区间:
1
≤
l
i
≤
r
i
≤
n
1\le l_i\le r_i \le n
1≤li≤ri≤n 2.3
1
≤
n
≤
1
e
5
,
1
≤
m
≤
100
,
1
≤
a
i
≤
1
e
9
,
1
≤
k
≤
1
e
9
1\le n\le 1e5,1\le m\le 100,1\le a_i\le 1e9,1\le k\le 1e9
1≤n≤1e5,1≤m≤100,1≤ai≤1e9,1≤k≤1e9
题解: 3.1 set,线段树维护区间最大值以及最小值都会超时!!!! 3.2 提示:应该用ST表(时间复杂度一会再来研究)(单词查询时间复杂度为
O
(
1
)
O(1)
O(1)) 3.3 具体的见上面模板,怎么
O
(
1
)
O(1)
O(1)查询区间最大值&区间最小值
代码:
#include<bits/stdc++.h>// #define int long long#definelllonglong#definedbg(x) cout << #x <<"==="<< x << endlusingnamespace std;constint N =1e5+10;int n, m, a[N], k;int Log[N], Bit[N];int fmi[N][25], fmx[N][25];voidinit(){
Bit[0]=1, Log[1]=0;for(int i =1; i <=20; i++) Bit[i]= Bit[i -1]*2;for(int i =2; i <= n; i++) Log[i]= Log[i /2]+1;/*
i Log[i]
1 0
2 1
3 1
4 2
5 2
6 2
7 2
8 3
9 3
10 3
11 3
12 3
13 3
14 3
15 3
16 4
17 4
18 4
19 4
20 4
21 4
22 4
23 4
24 4
25 4
26 4
27 4
28 4
29 4
30 4
*///一般来说,不超出访问区间就ok了}boolok(int l,int r,int k){int s = Log[r - l +1];//这里不超出访问区间就ok了int mx =max(fmx[l][s], fmx[r - Bit[s]+1][s]);int mi =min(fmi[l][s], fmi[r - Bit[s]+1][s]);return(mx - mi)<= k;}signedmain(){
cin >> n >> m;init();for(int i =1; i <= n; i++){scanf("%d",&a[i]);
fmi[i][0]= fmx[i][0]= a[i];}for(int j =1; j <=20; j++){//这个i+Bit[j]-1也很精髓for(int i =1; i + Bit[j]-1<= n; i++){//拆成两个区间
fmi[i][j]=min(fmi[i][j -1], fmi[i + Bit[j -1]][j -1]);
fmx[i][j]=max(fmx[i][j -1], fmx[i + Bit[j -1]][j -1]);}}/*
for (int i = 1; i <= n; i++) {
dbg(i);
for (int j = 0; j <= 20 && i + Bit[j] - 1 <= n; j++) {
// cout << fmi[i][j] << " ";
// cout << fmx[i][j] << " ";
}
cout << "\n";
}
*/
ll sum =1ll* n *(n +1)/2, ans;while(m--){scanf("%d",&k);
ans = sum;int r =0;for(int i =1; i <= n; i++){//查询区间极差复杂度达到O(1)while(r < n &&ok(i, r +1, k))++r;// cout << i << " " << r << endl;
ans -=1ll*(r - i +1);}printf("%lld\n", ans);}return0;}