A-B Problem(Dec)解题报告 - 单调队列

Problem #1: A-Bdec

Description

      出题是一件痛苦的事情!

         题目看多了也有审美疲劳,于是我舍弃了大家所熟悉的A+B Problem,改用A-B了哈哈!

         好吧,题目是这样的:给出一串数以及一个数字C,要求计算出所有A-B=C的数对的个数。(不同位置的数字一样的数对算不同的数对)

Input Format

      第一行包括2个非负整数NC,中间用空格隔开。

         第二行有N个整数,中间用空格隔开,作为要求处理的那串数。

Output Format

      输出一行,表示该串数中包含的所有满足A-B=C的数对的个数。

Sample Input
4 1
1 1 2 3

Sample Output

      3

Data Limit

      对于90%的数据,N <= 2000

         对于100%的数据,N <= 200000

         所有输入数据都在longint范围内。


算法分析:

这题相对来说比较难,但却可以用一种数据结构:单调队列来优化。最后应该说是可以对的。当然,还要有个排序。不过,其实还有另外一种思路,首先以O(nlog2n)快速排序,再以O(n)来一次遍历,将重复的合并到一起,最后进行n次O(log2n)的二分查找:比如,假设当前遍历值为K则进行两次二分,一次假定K相当于A,一次假定K相当于B,最后累计答案。当然,这样可能会出现重复查找的问题,所以最好也设多几个布尔数组来判断(仅仅只是灵机一动想出来的,不是程序的算法)。这题真正的算法是类似队列的思想。

#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
int input[100001];
int n,c,num[100001],ge[100001],p,pp,k=0,head=0,tail=0;
long long ans=0;
using namespace std;
int main()
{
memset(ge,0,sizeof(ge));
scanf("%d %d %d",&n,&c,&p);
num[0]=p;
ge[0]=1;
for (int i=1;i<n;++i){
scanf("%d",&input[i]);
}
sort(input+0,input+n);
for(int i=1;i<n;++i)
{
pp=input[i];
if(pp==p)
++ge[k];
else
{
++k;
++ge[k];
num[k]=pp;
p=pp;
}
}
while(head<n-1)
{
while(num[head]-num[tail]>c) ++tail;

while(num[head]-num[tail]<c) ++head;

if(num[head]-num[tail]==c)
{
ans+=(ge[head]*ge[tail]);
++tail;++head;
}
}
printf("%d\n",ans);
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值