HDU 5289--Assignment

题目网址

题意:对于已知数组a,求子区间个数满足最大最小值的差值不超过k的子区间个数

思路:从头开始遍历,记录最大最小值得位置和值,当最大最小值超过k时,表示前面的区间可以自由选择连续区间都满足要求,然后可以继续从靠左的最大值或者最小值的下一个位置开始遍历,重新记录最大最小值。重点是记录上一个选定的区间,当后面选择的区间与前面选择的区间有重合时,要减去重合的部分,并且最后了要统计一下

代码:

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
int n,k,T,a[100005];
long long ans,l,r,x,y,minn,maxx,px,pn,re,en;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
       scanf("%d%d",&n,&k);
       for(int i=1;i<=n;i++)
       {
           scanf("%d",&a[i]);
       }
       l=r=ans=0;
       minn=0x3f3f3f3f;
       maxx=-1;
       re=1;
        for(int i=1;i<=n;i++)
        {//cout<<i<<" "<<a[i]<<" "<<maxx<<" "<<minn<<" !!"<<endl;
            if(maxx-a[i]>=k||a[i]-minn>=k)
            {
                en=i-1;
                if(re<=r)
                {
                    x=r-re+1;
                }
                else x=0;
                ans+=(en-re+2)*(en-re+1)/2;
                ans-=x*(x+1)/2;
                //cout<<i<<" "<<ans<<" "<<re<<" "<<en<<" "<<endl;
                l=re;r=en;
                re=min(pn,px)+1;
                i=re;
                minn=0x3f3f3f3f;
                maxx=-0x3f3f3f3f;
            }
            if(a[i]<minn) {minn=a[i];pn=i;}
            if(a[i]>maxx) {maxx=a[i];px=i;}
        }
        en=n;
        if(re<=r)
                {
                    x=r-re+1;
                }
                else x=0;
                ans+=(en-re+2)*(en-re+1)/2;
                ans-=x*(x+1)/2;
                printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37868325/article/details/81071070
hdu