您的位置:首页 > 其它

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

2015-07-22 21:24 387 查看
题目链接: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 0x3f3f3f3f
const int MAXN=100005;
#define mod 1000000007

int 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 0x3f3f3f3f
const int MAXN=100005;
#define mod 1000000007

int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: