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
output
input
output
input
output
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
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
相关文章推荐
- Codeforces 847 B. Preparing for Merge Sort (二分)
- Codeforces 760B Frodo and pillows【贪心+二分】
- Codeforces 604B - Alan Wake(二分)
- Codeforces 493C. Vasya and Basketball【暴力+二分】
- Codeforces 651D:Image Preview 二分
- CodeForces 377B Preparing for the Contest 贪心(二分加优先队列)
- codeforces 274A. k-Multiple Free Set【二分】
- Codeforces 701D. As Fast As Possible(二分)
- Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort(暴力)
- 【打CF,学算法——三星级】CodeForces 645C Enduring Exodus (二分+贪心)
- codeforces 817C Really Big Numbers 二分
- CodeForces - 620D Professor GukiZ and Two Arrays 二分 | 双指针 STL
- Codeforces 894.D Ralph And His Tour in Binary Country (预处理、二分)
- CodeForces 68B Energy exchange (二分查找)
- codeforces 626C 二分判定
- 二分--CodeForces - 660C(二分的应用,也可以用尺取)
- 【CodeForces 208E】Blood Cousins dps序+二分
- codeforces 609D D. Gadgets for dollars and pounds(二分+贪心)
- codeforces 487B B. Strip(rmq+线段树+二分)
- CodeForces 627D Preorder Test(树形DP+二分)