hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)

来源:互联网 发布:阿里云给我打电话 编辑:程序博客网 时间:2024/05/17 00:14

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289

题意:给你n个数和k,求有多少的区间使得区间内部任意两个数的差值小于k,输出符合要求的区间个数

思路:求出区间的最大最小值,只要他们的差值小于k,那么这个区间就符合要求,但是由于n较大,用暴力一定超时,所以就要用别的方法了;而RMQ是可以求区间的最值的,而且预处理的复杂度只有O(nlogn),而查询只是O(1)处理,这样相对来说节约了时间,再根据右端点来二分枚举左端点(其实不用二分好像更快,估计是数据问题)。

而另一种方法不得不说,学了C++的一定要在认真的去看一下STL的那些用法,这次用multiset来做就大大的节约时间,而且又不用思考太多,只要从左到右模拟区间,就可以了。


(RMQ+二分)代码:

#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <queue>#include <algorithm>#include <vector>#include <set>using namespace std;#define LL __int64#define INF 0x3f3f3f3fconst int MAXN=100005;#define mod 1000000007int a[MAXN];LL ans;int dp1[MAXN][30],dp2[MAXN][30];void init(int n){    for(int i=1;i<=n;i++)        dp1[i][0]=dp2[i][0]=a[i];    for(int j=1;(1<<j)<=n;j++)    {        for(int i=1;i+(1<<j)-1<=n;i++)        {            dp1[i][j]=max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]);            dp2[i][j]=min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]);        }    }}int RMQ(int L,int R){    int k=0;    while((1<<(k+1))<=R-L+1)k++;    return max(dp1[L][k],dp1[R-(1<<k)+1][k])-min(dp2[L][k],dp2[R-(1<<k)+1][k]);}int binarySearch(int L,int R,int n,int k){    int mid;    int l=L,r=R;    while(l<=r)    {        mid=(l+r)/2;        if(RMQ(mid,R)>=k)        {            l=mid+1;        }        else        {            r=mid-1;        }    }    if(RMQ(mid,R)>=k)        mid++;    return mid;}int main(){    int T,i,j,n,k,mi,ma,l,r;    while(~scanf("%d",&T))    {        while(T--)        {            scanf("%d%d",&n,&k);            for(i=1;i<=n;i++)                scanf("%d",&a[i]);            if(!k)            {                printf("0\n");                continue;            }            if(k==1)            {                printf("%d\n",n);                continue;            }            init(n);            ans=0;            for(i=j=1;i<=n;i++)            {                j=binarySearch(j,i,n,k);                ans+=i-j+1;            }            printf("%I64d\n",ans);        }    }    return 0;}


(STL)代码:

#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <queue>#include <algorithm>#include <vector>#include <set>using namespace std;#define LL __int64#define INF 0x3f3f3f3fconst int MAXN=100005;#define mod 1000000007int a[100005];LL ans;int main(){    int T,i,j,n,k,mi,ma,l,r;    while(~scanf("%d",&T))    {        while(T--)        {            scanf("%d%d",&n,&k);            for(i=0;i<n;i++)                scanf("%d",&a[i]);            if(!k)            {                printf("0\n");                continue;            }            if(k==1)            {                printf("%d\n",n);                continue;            }            l=0;            r=1;            multiset<int>s;            s.insert(a[0]);            ans=n;            while(1)            {                if(s.size())                {                    mi=*s.begin();                    ma=*s.rbegin();                    if(abs(a[r]-mi)<k&&abs(a[r]-ma)<k)                    {                        ans+=s.size();                        s.insert(a[r]);                        r++;                        if(r==n)                            break;                    }                    else                    {                        if(s.size())                            s.erase(s.find(a[l]));                        l++;                    }                }                else                {                    l=r;                    s.insert(a[r]);                    r++;                    if(r==n)                        break;                }            }            printf("%I64d\n",ans);        }    }    return 0;}


0 0
原创粉丝点击