1. 程式人生 > >5101 Select (二分)

5101 Select (二分)

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.  So, he needs to select two classmates as his teammates.  In this game, the IQ is very important, if you have low IQ you will WanTuo. Dudu's IQ is a given number k. We use an integer v[i] to represent the IQ of the ith classmate.  The sum of new two teammates' IQ must more than Dudu's IQ.  For some reason, Dudu don't want the two teammates comes from the same class.  Now, give you the status of classes, can you tell Dudu how many ways there are.

Input

There is a number T shows there are T test cases below. (T≤20T≤20)  For each test case , the first line contains two integers, n and k, which means the number of class and the IQ of Dudu. n ( 0≤n≤10000 ), k( 0≤k≤2^{31} ).  Then, there are n classes below, for each class, the first line contains an integer m, which means the number of the classmates in this class, and for next m lines, each line contains an integer v[i], which means there is a person whose iq is v[i] in this class. m( 0≤m≤1000≤m≤100 ), v[i]( 0≤v[i]<2^{31}

 )

Output

For each test case, output a single integer.

Sample Input

1
3 1
1 2
1 2
2 1 1

Sample Output

5

題目大意:從n個班的學生中選取兩個學生,這兩個學生需滿足:不在同一個班,兩個人的IQ和大於K,輸出總共的方案數

解題思路: 想明白了這道題就好做了,首先我們可以求出每一個班的學生中滿足條件的方案數,然後把所有的學生放在一起再求滿足條件的方案數,後者減去前者即為答案,再求有多少種方案時,先sort排下序,從第一個學生開始,找到滿足條件的第二個學生的位置l(這個學生是符合條件時IQ的最小值,因為排過序,後面的學生都滿足,與第一個學生配備的方案數就是m-l)

剛開始使用cin輸入TL了,然後用std::ios::sync_with_stdio(false)來取消cin與stdin的同步,加快cin的輸入效率依然TL,最後用scna輸入才過,看來即使取消cin與stdin的同步cin的輸入所需時間還是比scanf用的多。

AC程式碼:

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1100;
ll a[maxn],b[maxn*maxn];
int main() 
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		ll n,m;
		ll cnt=0;//總人數 
		ll k,sum=0;
		scanf("%lld%lld",&n,&k);
		for(ll i=0;i<n;i++)
		{
			scanf("%lld",&m);
			for(ll j=0;j<m;j++)
			{
				scanf("%lld",&a[j]);
				b[cnt++]=a[j];
			}
			sort(a,a+m);
			for(ll j=0;j<m;j++)//同一班中從第一個學生開始一次找符合條件的方案數 
			{
				ll l=j+1,r=m-1;
				while(l<=r)
				{
					ll mid=(l+r)/2;
					if(a[j]+a[mid]>k)
					{
						r=mid-1;	
					}
					else
						l=mid+1;
				}
				sum-=m-l;
			}	
		}
		sort(b,b+cnt);
		for(ll j=0;j<cnt;j++)//所有學生中滿足條件的方案數 
		{
			ll l=j+1,r=cnt-1;
			while(l<=r)
			{
				ll mid=(l+r)/2;
				if(b[j]+b[mid]>k)
				{
					r=mid-1;
				}
				else
					l=mid+1;
			}
			sum+=cnt-l;
		}
		printf("%lld\n",sum);
	}
	return 0;
}