题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5101
解题思路:
BestCoder官方题解:
题目大意:
给定一些集合,选择两个来自不同集合的数,加和大于k,问有多少种选择方案。
解题思路:
答案=从所有数中选择的两个加和大于k的数的方案数-在同一个集合中选择的两个加和大于k的数的方案数
而对于同一个集合中选择的两个加和大于k的方案数是可以直接排序然后利用单调性快速统计出来的。
暴力会超时,最简单的做法就是二分,下面分别给出函数的二分和STL里面的二分。希望大家有所收获。
AC代码(函数的二分查找(1)):
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; int a[1010]; int b[1010][110]; int ss[1010*110]; ll solve(int ss[],int l,int r,int key){ int R = r; ll ans = -1; while(l <= r){ int mid = (l+r)>>1; if(ss[mid] > key) ans = mid; if(ss[mid] > key) r = mid-1; else l = mid+1; } if(ans == -1) return 0; return R-ans+1; } int main(){ int T; scanf("%d",&T); while(T--){ int k,n,m=0; ll ans = 0; scanf("%d%d",&n,&k); for(int i = 0; i < n; i++){ scanf("%d",&a[i]); for(int j = 0; j < a[i]; j++){ scanf("%d",&b[i][j]); ss[m++] = b[i][j]; } } for(int i = 0; i < n; i++) sort(b[i],b[i]+a[i]); sort(ss,ss+m); for(int i = 0; i < n; i++) for(int j = 0; j < a[i]; j++){ ll t1 = solve(ss,0,m-1,k-b[i][j]); ll t2 = solve(b[i],0,a[i]-1,k-b[i][j]); ans += t1-t2; } printf("%I64d\n",ans>>1); } return 0; }
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; int a[110]; int ss[1010*110]; ll solve(int ss[],int l,int r,int key){ int R = r; ll ans = -1; while(l <= r){ int mid = (l+r)>>1; if(ss[mid] > key) ans = mid; if(ss[mid] > key) r = mid-1; else l = mid+1; } if(ans == -1) return 0; return R-ans+1; } int main(){ int T; scanf("%d",&T); while(T--){ int k,n,m = 0,t; ll t1 = 0,t2 = 0; scanf("%d%d",&n,&k); for(int i = 0; i < n; i++){ scanf("%d",&t); for(int j = 0; j < t; j++){ scanf("%d",&a[j]); ss[m++] = a[j]; } sort(a,a+t); for(int j = 0; j < t; j++) t2 += solve(a,0,t-1,k-a[j]); } sort(ss,ss+m); for(int i = 0; i < m; i++) t1 += solve(ss,0,m-1,k-ss[i]); printf("%I64d\n",(t1-t2)>>1); } return 0; }
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; int a[110]; int ss[1010*110]; int main(){ int T; scanf("%d",&T); while(T--){ int k,n,m = 0,t,pos; ll t1 = 0,t2 = 0; scanf("%d%d",&n,&k); for(int i = 0; i < n; i++){ scanf("%d",&t); for(int j = 0; j < t; j++){ scanf("%d",&a[j]); ss[m++] = a[j]; } sort(a,a+t); for(int j = 0; j < t; j++){ pos = upper_bound(a,a+t,k-a[j])-a; t2 += (ll)(t-1-pos+1); } } sort(ss,ss+m); for(int i = 0; i < m; i++){ pos = upper_bound(ss,ss+m,k-ss[i])-ss; t1 += (ll)(m-1-pos+1); } printf("%I64d\n",(t1-t2)>>1); } return 0; }