题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5101
Problem Description One day, Dudu, the most clever boy, heard of ACM/ICPC, which is a very interesting game. He wants to take part in the game. But as we all know, you can't get good result without teammates. Input There is a number T shows there are T test cases below. (T≤20 ) Output For each test case, output a single integer. Sample Input 1
扫描二维码关注公众号,回复:
4337180 查看本文章
5 |
题目大意,给出T组测试数据,n个班级和一个人的智商k,对于每个班级,首先输入这个班的人数,然后按顺序输入这些人的智商,要找两个分别在不同班级的人&&他们的智商之和大于k,问有多少中组合。
分析,如果对于每个人都找一遍的话,用二分,复杂度为O(n*m*log(n*m)),看看数据范围,可行
使用二分总结中的 5.查找第一个大于key的元素的位置 和 6.查找最后一个小于等于key的元素的位置
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
//#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
const int MAXN=1e6+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
ll room[1010][110],arr[MAXN];
ll n,k;
int main()
{
//std::ios::sync_with_stdio(false);
int T;
while(cin>>T)
{
while(T--)
{
clean(arr,0);
clean(room,0);
scanf("%lld%lld",&n,&k);
int tot=0;
for(int i=1;i<=n;++i)
{
scanf("%lld",&room[i][0]);
for(int j=1;j<=room[i][0];++j)
{
scanf("%lld",&room[i][j]);
//cin>>room[i][j];
arr[tot++]=room[i][j];
}
sort(room[i]+1,room[i]+room[i][0]+1);
}
sort(arr,arr+tot);//默认从低到高
ll ans=0;
// for(int i=1;i<=n;++i)
// cout<<room[i][0]<<endl;
for(int i=1;i<=n;++i)
{
//对于每个人,找出第一个大于k的位置
//再减去本班符合要求的人数
for(int j=1;j<=room[i][0];++j)
{
int l=0,r=tot-1,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(room[i][j]+arr[mid]>k)
r=mid-1;
else if(room[i][j]+arr[mid]<=k)
l=mid+1;
}
//l为第一个大于k的位置
ll res1=tot-l;
//找出最后一个小于等于k的位置
l=1,r=room[i][0];
while(l<=r)
{
mid=(l+r)>>1;
if(room[i][j]+room[i][mid]>k)
r=mid-1;
else if(room[i][j]+room[i][mid]<=k)
l=mid+1;
}
//r为最后一个位置
ll res2=room[i][0]-r;
//cout<<res1<<" "<<res2<<endl;
ans+=(res1-res2);
}
}
printf("%lld\n",ans/2);
//cout<<ans/2<<endl;
}
}
}
/*
Sample Input
1
3 1
1 2
1 2
2 1 1
Sample Output
5
*/