HDU-5101-Select(二分)
題目連線: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 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
*/