time limit per test 1 second
memory limit per test 256 megabytes
题目链接http://codeforces.com/problemset/problem/1166/C
昨天打这场有点惨,A题写了一个半小时,数错数了。。。然后这题写的就有点仓促,想到正解后只剩10分钟不到了。。。但我还是五分钟写完,然后由于时间不够了就没怎么检查。。。所以WA了4次后A了。。。只拿了500分。。。。
题目大意:给你一个数列,让你寻找有多少对不同的数使得|x-y|到|x+y|可以覆盖|x|到|y|。
实际上仔细想想就会发现当|x|>=1/2|y|的时候就成立了。
比如拿上面的5 2 -3来说,之所以5和2不成,就是因为|5-2|>|2|,即|y-x|>|x|,我们大概就差不多可以知道一点点方法了。
接下来就是寻找每个数有多少个大于等于他的一半,这个我们就可以用排序后二分来查找,当然,排序前要去重然后取abs
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
const int mac=2e5+50;
#define ll long long
int a[mac],b[mac];
int ok(int x,int y)
{
if (x<=y*2) return 1;
return 0;
}
int main()
{
int n;
scanf ("%d",&n);
for (int i=1; i<=n; i++){
scanf ("%d",&a[i]);
}
sort(a+1,a+1+n);
int p=a[1],num=1;
b[1]=a[1];
for (int i=2; i<=n; i++){
if (a[i]!=p) b[++num]=a[i],p=a[i];
}
for (int i=1; i<=num; i++)
if (b[i]<0) b[i]=-b[i];
sort(b+1,b+1+num);
ll tot=0;
for (int i=1; i<=num; i++){
int l=i,r=num,mid,ans=i;
for (int j=1; j<=22; j++){
mid=(l+r)>>1;
if (ok(b[mid],b[i])){
l=mid+1;
ans=mid;
}
else r=mid-1;
}
tot+=ans-i;
}
cout<<tot<<endl;
return 0;
}