标签:等于 定义 问题 print 条件 记录 select 一个 lld
题目链接
题目大意:给你n个教室以及每个教室的同学的智商,让你从两个不同的教室之中分别选一个人,这两人的智商之和要比k大(注意是大不是大于等于),问有多少种方法。
??又是一道没有看清题面的题TAT
??如果不考虑选的两个人不能在同一间教室的话,可以先让所有人的智商排序,然后遍历所有人的智商,对于每一个人, 如果有另一个人的智商和他加起来比k大的话,那么不小于这"另一个人"的智商的所有人都可以选。很显然这个问题用二分就能解决了。那如果选的两个人不能在同一间教室的话呢?那么只要所有人中满足条件的人数减去同一间教室里面满足条件的人数就行了。这里我们也需要一个二分。
??所以说思路就是定义一个一维数组\(a\)和一个二维数组\(b\),对\(a\)和\(b\)的每个子数组\(b[i]\)都进行排序,然后依次遍历二维数组\(b\)的每个子数组\(b[i]\)中的元素\(b[i][j]\),并用二分求出\(a\)中满足条件的人数和\(b[i]\)中满足条件的人数,两者之差的累加和就是答案。
const int maxn = 1e5+10;
int arr[maxn], classes[1005][105], cnt[maxn];
int main(void) {
int t;
scanf("%d", &t);
while(t--) {
int n, k, kase = 0;
scanf("%d%d", &n, &k);
for (int i = 0; i<n; ++i) {
int m;
scanf("%d", &m);
cnt[i] = m; //记录二维数组每个子数组的元素个数
for (int j = 0; j<m; ++j) {
scanf("%d", &classes[i][j]);
arr[kase++] = classes[i][j];
}
sort(classes[i], classes[i]+m);
}
sort(arr, arr+kase);
ll ans = 0;
for (int i = 0; i<n; ++i)
for (int j = 0; j<cnt[i]; ++j) {
int tmp = k-classes[i][j]+1; //因为两人智商和要比k大所以别忘了+1
int num1 = kase-int(lower_bound(arr, arr+kase, tmp)-arr);
int num2 = cnt[i]-int(lower_bound(classes[i], classes[i]+cnt[i], tmp)-classes[i]);
ans += ll(num1-num2);
}
printf("%lld\n", ans/2);
}
return 0;
}
标签:等于 定义 问题 print 条件 记录 select 一个 lld
原文地址:https://www.cnblogs.com/shuitiangong/p/12639905.html