玲珑学院OJ 1149-Buildings-(RMQ+二分)

来源:互联网 发布:php json格式化输出 编辑:程序博客网 时间:2024/06/05 16:32

题目链接:http://www.ifrog.cc/acm/problem/1149

大致题意:给你n个数,问你这n个数中有多少个子区间的最大值减最小值小于等于k

题目思路:首先预处理一波区间最大最小值,RMQ跑一发即可(具体见代码),之后二分查找当前符合条件的子区间有多少个即可。。。。听说单调队列更省时?

#include<map>    #include<stack>    #include<queue>  #include<vector>    #include<math.h>    #include<stdio.h>  #include<iostream>#include<string.h>    #include<stdlib.h>    #include<algorithm>    using namespace std;    typedef long long  ll;    #define inf 1000000000    #define  mod 1000000007   #define  maxn  200005#define  INF 9223372036854775807LL#define  lowbit(x) (x&-x)    #define  eps 1e-10  int a[maxn],b[maxn],mx[maxn][25],mn[maxn][25],n,k;void RMQ(){int i,j;memset(mn,127,sizeof(mn));for(i=1;i<=n;i++)mx[i][0]=mn[i][0]=a[i];for(j=1;(1<<j)<=n;j++)for(i=1;i+(1<<j)-1<=n;i++){mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);}}bool check(int x,int y){int kk=0;while((1<<(kk+1))<=y-x+1)kk++;int maxs=max(mx[x][kk],mx[y-(1<<kk)+1][kk]);int mins=min(mn[x][kk],mn[y-(1<<kk)+1][kk]);if(maxs-mins<=k)return 1;return 0;}int  main(void){ll sum=0;int i,l,r,mid,ans;scanf("%d%d",&n,&k);for(i=1;i<=n;i++)scanf("%d",&a[i]);RMQ();for(i=1;i<=n;i++){l=i;r=n;ans=i-1;while(l<=r){mid=(l+r)/2;if(check(i,mid)){ans=mid;l=mid+1;}elser=mid-1;}sum+=ans-i+1;}printf("%d\n",sum);return 0;}