bc#31-1 pairs
http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?pid=1001&cid=569
数轴上有n个点(x[i],0),(i=0,1,2,…,n−1),求解有几对点使得
<a,b> that |x[b]−x[a]|≤k.(a<b)
case: -100 0 100 101 102 有3对点满足
1.一开始想到的是二分查找,结果发现有o(n)的方法,只需将序列遍历一遍i++ j++即可
2.注意int溢出,用long long,题目数据范围是1≤n≤100000,而n*n就会溢出,有一定欺骗性
二分:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int a[100010]; int n,k; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(int i=0;i<n;i++)scanf("%d",&a[i]); sort(a,a+n); long long sum=0; for(int i=0;i<n;i++) { int p=lower_bound(a,a+n,a[i]+k)-a; if(p==n)p=p-i-1; else { if(a[p]-a[i]>k)p=p-i-1; else p=p-i; } sum+=p; } printf("%lld\n",sum); } return 0; }
O(n)方法
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> using namespace std; int n,k,a[110000]; void solved(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]); sort(a+1,a+n+1); int z=1; long long ans=0; for(int i=2;i<=n;i++){ while(a[i]-a[z]>k)++z; ans+=i-z; } cout<<ans<<endl; } int main(){ int T; scanf("%d",&T); while(T--)solved(); return 0; }