因为每次要找其他班和自己相加之和大于固定值的人数的个数,所以先排序,利用二分查找找到满足条件的最小值,然后后面的均符合条件,利用容斥定理中的补集关系,让总的排列中满足条件的个数-自己班中满足条件的个数=其他班满足条件的个数,二分查找自己写的,不熟悉的可以用stl里的upper_bound函数
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 1007
#define N 107
using namespace std;
int a[MAX][N];
int b[MAX*N];
int sum[MAX];
bool cmp ( int a , int b )
{
return a > b;
}
int get ( int v , int a[] , int len )
{
int left = 1 , right = len , mid;
while ( left < right )
{
mid = (left + right+1) >> 1;
if ( a[mid] > v ) left = mid;
else right = mid -1;
}
if ( a[left] > v )
return left;
else return 0;
}
int main ( )
{
int t,n,k,iq;
scanf ( "%d" , &t );
while ( t-- )
{
scanf ( "%d%d" , &n , &k );
long long ans = 0;
int cnt = 1;
for ( int i = 1 ; i <= n ; i++ )
{
scanf ( "%d" , &sum[i] );
for ( int j = 1 ; j <= sum[i] ; j++ )
{
scanf ( "%d" , &a[i][j] );
b[cnt++] = a[i][j];
}
sort ( a[i]+1 , a[i]+sum[i]+1 , cmp );
}
sort ( b+1 , b+cnt , cmp );
for ( int i = 1 ; i <= n ; i++ )
for ( int j = 1 ; j <= sum[i] ; j++ )
{
long long temp = get ( k-a[i][j] , b , cnt-1 );
temp -= get ( k-a[i][j] , a[i] , sum[i] );
ans += temp;
}
printf ( "%I64d\n" , ans/2 );
}
}