您的位置:首页 > 其它

codeforces 895/B sort+二分

2017-12-27 08:14 375 查看
B. XK Segments

time limit per test
1 second

memory limit per test
256 megabytes

input
standard input

output
standard output

While Vasya finished eating his piece of pizza, the lesson has already started. For being late for the lesson, the teacher suggested Vasya to solve one interesting problem. Vasya has an array a and
integer x. He should find the number of different ordered pairs of indexes (i, j) such
that ai ≤ aj and
there are exactly k integers y such
that ai ≤ y ≤ aj and y is
divisible by x.

In this problem it is meant that pair (i, j) is equal to (j, i) only
if i is equal to j.
For example pair (1, 2) is not the same as (2, 1).

Input

The first line contains 3 integers n, x, k (1 ≤ n ≤ 105, 1 ≤ x ≤ 109, 0 ≤ k ≤ 109),
where n is the size of the array a and x and k are
numbers from the statement.

The second line contains n integers ai (1 ≤ ai ≤ 109) —
the elements of the array a.

Output

Print one integer — the answer to the problem.

Examples

input
4 2 1
1 3 5 7


output
3


input
4 2 0
5 3 1 7


output
4


input
5 3 1
3 3 3 3 3


output
25


Note

In first sample there are only three suitable pairs of indexes — (1, 2), (2, 3), (3, 4).

In second sample there are four suitable pairs of indexes(1, 1), (2, 2), (3, 3), (4, 4).

In third sample every pair (i, j) is suitable, so the answer is 5 * 5 = 25.

题目大致的意思是说给你n个数
ai ....aj
其中1<=i<=j<=n

然后有一个x
和k 你要寻找所有的序列 使得

这个序列中的从第一个元素到最后一个元素(包括这两个)之间恰好有k个可以被x整除

看用例第一个用例就是让我们找到所有的序列满足他们之间最多被2整除的数有一个

那么1,3 3,5 5,7 是这样的唯一三组数
对应的下标为 (1, 2), (2, 3), (3, 4)

那如果是 (1,3)呢  这样的话 1,2,3,4,5 中间2,4都可以被2整除 就不满足只有一个的情况了。

最后要你输出的是所有这样的序列数之和。

解题思路:

可以看出,如果打乱原序列是不会改变所得结果的个数的,其实这个证明起来也不难,但是我觉得没有必要把时间浪费在这里

当时就这么做了,其实也是怀着猜的心态,但是后来感觉还好。因为他说(i,j) 和(j,i)不是一对的, 所以如果你(i,j)原来是满足的话

那么如果排序后打乱顺序,他们在的位置是(i2,j2) 或者(j2,i2)一定有且唯一有一个满足条件。具体的话有兴趣的可以自己尝试一下,

重点是sort之后可以用二分 可以缩短时间复杂度,故想到排序这样。

那么我们对这组数进行排序之后 开始用二分查找,怎么查找呢?

我分了几类讨论,在代码中有注释,如果想自己再试下我先说个思路 

被 x整数的有k个 那么对于 第a[i]的数来说 可以允许的数大约是k*x+a[i附近(当然要考虑余数的情况)

可以允许最大的数确定了之后允许的最小的数也就确定 max-(x-1)  就是

比如你是要被5整数  你现在是1 然后 只允许有一个 所以是 5-9 都可以 10 就又可以被整除了 不能要

而如果是4的话 一个都没有 也不可以

照着这个思路程序如下:

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;
typedef long long ll;

struct node
{
ll num,val;
};
node a[100005];

bool cmp(const node&a,const node &b)
{
if(a.val!=b.val) return a.val<b.val;
else return a.num<b.num;
}
//两种二分方式
inline ll bis1(ll,ll);
inline ll bis2(ll,ll);
//key1 key2 分别代表当前数允许的最小值和最大值
ll n,x,k,key1,key2;
int main()
{
scanf("%lld%lld%lld",&n,&x,&k);
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i].val);
a[i].num=i+1;
}
sort(a,a+n,cmp);

ll ans=0;
ll len;
ll l,r;
for(int i=0;i<n;i++)
{
//分了四类情况
//第一类是当前数整除但是只有0个整数 直接continue
//第二类是当前数整除 k不等于0 修正key1
//第三类是k==0 修正key2
if(a[i].val%x==0&&k==0) continue;
else if(a[i].val%x==0&&k!=0)
{
key1=a[i].val+x*(k-1);
key2=key1+x-1;
}
else if(a[i].val%x!=0&&k==0)
{
key1=a[i].val;
key2=key1+x-1-a[i].val%x;
}
else
{
key1=a[i].val+k*x-a[i].val%x;
key2=key1+x-1;
}
//考虑两种情况 一种是查最小的时候 要优先选左侧的 查最大的优先右侧
//就是改变等号归哪边的事
l=bis1(0,n-1);
r=bis2(0,n-1);
if(a[r].val>=key1)
ans+=r-l+1;
}

printf("%lld\n",ans);
return 0;
}

inline ll bis1(ll l,ll r)
{
if(r<=l+1)
{
if(a[l].val>=key1) return l;
else return r;

}
ll mid=(l+r)/2;
if(key1<a[mid].val) bis1(mid,r);
else bis1(l,mid);
}

inline ll bis2(ll l,ll r)
{
if(r<=l+1)
{
if(a[r].val<=key2) return r;
else return l;
}
ll mid=(l+r)/2;
if(key2>=a[mid].val) bis2(mid,r);
else bis2(l,mid);
}我承认有点麻烦..不过最后一A还是很开心的啊hh
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM