HDU 5289 Assignment (RMQ+二分)

来源:互联网 发布:幺正矩阵 编辑:程序博客网 时间:2024/05/16 17:10

求任意区间满足R-L< K 的数量

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <queue>#include <cmath>using namespace std;typedef long long LL;const int inf = 0x3f3f3f3f;const double oo = 10e9;const double eps = 10e-9;const int MAXN = 100010;//int dp[MAXN][20];int maxsum[MAXN][20],minsum[MAXN][20];int mm[MAXN],a[MAXN];void intRMQ(int n,int b[]){    mm[0]=-1;    for(int i=1; i<=n; ++i)    {        mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];        //dp[i][0]=b[i];        maxsum[i][0]=minsum[i][0]=b[i];    }    for(int j=1; j<=mm[n]; ++j)  //for(int j=1;(1<<j)<=n;++j)        for(int i=1; i+(1<<j)-1<=n; ++i)        {            //dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);            maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]);            minsum[i][j] = min(minsum[i][j - 1], minsum[i + (1 << (j - 1))][j - 1]);        }}int rmq(int x,int y){    int k=mm[y-x+1];    return max(maxsum[x][k],maxsum[y-(1<<k)+1][k]);}int rmq2(int x,int y){    int k=mm[y-x+1];    return min(minsum[x][k],minsum[y-(1<<k)+1][k]);}int main(){    int n,k;    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&k);        for(int i=1; i<=n; ++i)        {            scanf("%d",&a[i]);        }        intRMQ(n,a);        LL ans=0;        int q=1;        int l,r;        for(int i=1; i<=n; ++i)        {            l=q;            r=i;            while(l<=r)            {                int mid=(l+r)/2;                int high=rmq(mid,i);                int low=rmq2(mid,i);                int tmp=high-low;                if(tmp>=k)                    {                                l=mid+1;  //收缩查询空间                                //左边向右缩小                }                else if(tmp<k) //扩大查询空间                    r=mid-1;               }            q=l;            ans+=i-l+1;        }        printf("%I64d\n",ans);    }     return 0;}



0 0