题目地址
题意:给你一个长度为n的序列,问有多少子区间满足max-min<=k.
题解:当l固定时,随着r的增大,max会变大,min会变小,则max-min有单调性,我们二分得到r的最大值,则贡献为r-l+1(最值可以通过RMQ得到)。
代码:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
#include<queue>
#include<set>
#include<algorithm>
#include<map>
#include<math.h>
using namespace std;
typedef long long int ll;
typedef pair<int,int>pa;
const int N=1e6+10;
const int mod=1e9+7;
const ll INF=1e18;
const int inf=1e4;
int read()
{
int x=0;
char ch = getchar();
while('0'>ch||ch>'9')ch=getchar();
while('0'<=ch&&ch<='9')
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return x;
}
/***********************************************************/
const int maxn=2e5+10;
int maxnum[maxn][20];
int minnum[maxn][20];
int n,m;
void RMQ(int num)
{
for(int j=1; j<20; j++)
{
for(int i=1; i<=num; i++)
{
if(i+(1<<j)-1<=num)
{
maxnum[i][j]=max(maxnum[i][j-1],maxnum[i+(1<<(j-1))][j-1]);
minnum[i][j]=min(minnum[i][j-1],minnum[i+(1<<(j-1))][j-1]);
}
}
}
}
int solve(int l,int r)
{
int k=(int)((log(r-l+1))/log(2.0));
int max1,min1;
max1=max(maxnum[l][k],maxnum[r-(1<<k)+1][k]);
min1=min(minnum[l][k],minnum[r-(1<<k)+1][k]);
if(max1-min1<=m) return 1;
return 0;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1; i<=n; i++)
{
scanf("%d",&maxnum[i][0]);
minnum[i][0]=maxnum[i][0];
}
RMQ(n);
int ans=0;
for(int i=1; i<=n; i++)
{
int tot=i;
int l=i;
int r=n;
while(r>=l)
{
int mid=(r+l)>>1;
if(solve(i,mid))
{
tot=mid;
l=mid+1;
}
else
{
r=mid-1;
}
}
ans+=tot-i+1;
}
printf("%d\n",ans);
}
}