题解 | #Away from College#
Away from College
https://ac.nowcoder.com/acm/contest/11256/A
K King of Range
1.方法:st表加双指针
2.题意
给你一个长为n的数组,有m次询问,每次询问给你一个k,问有多少对(l,r),使数组区间l到r的最大值与最小值的差大于k
3.思路
若给你个子数组发现最大值与最小值的差已经满足条件,那么是不是意味着在这个子数组的基础上在添加其他的元素,其最大值与最小值的差也会成立。所以我们可以用双子针,固定i的位置,来找最小的j。要在一个区间内找最小值,我们可以用st表。
4.代码如下
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; }
ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int mod=1e9+7;
const int N=1e5+7;
int n,m,l,r;
int Log[N]; // 用来求log的
int stmax[N][22];
int stmin[N][22];
void fun(){//求log的函数
Log[1]=0;
for(int i=2;i<=n;i++)
Log[i]=Log[i/2]+1;
}
bool search(int l,int r,ll k){//判断区间l到r是否可以
int s=Log[r-l+1]; //求log的值
int ma=max(stmax[l][s], stmax[r-(1<<s)+1][s]);//区间最大值
int mi=min(stmin[l][s], stmin[r-(1<<s)+1][s]);//区间最小值
if(ma-mi>k) return true; //判断是否大于k
else return false;
}
int main(){
while(cin>>n>>m){
fun();
for(int i=1;i<=n;i++) {cin>>stmax[i][0];stmin[i][0]=stmax[i][0];}
for(int j=1;j<=21;j++)//构造st表
for(int i=1;i+(1<<j)-1<=n;i++){
stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
stmin[i][j]=min(stmin[i][j-1],stmin[i+(1<<(j-1))][j-1]);
}
while(m--){
ll k,ans=0;
cin>>k;
for(int i=1,j=1;i<=n;i++){
while(!search(i,j,k)&&j<=n&&i<=j){//固定i的值,找到成立的j的最小值
j++;
}
if(j<=n) ans=ans+n-j+1; //如果某一子段可以,则无论后面加上什么数形成的数组都可以
}
cout<<ans<<endl;
}
}
return 0;
}
查看7道真题和解析