HDU - 5101 - Select(简单思维)

Posted shuitiangong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 5101 - Select(简单思维)相关的知识,希望对你有一定的参考价值。

题目链接
题目大意:给你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
", ans/2);
    }
    return 0;
}

以上是关于HDU - 5101 - Select(简单思维)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6124 17多校7 Euler theorem(简单思维题)

HDU 6090 17多校5 Rikka with Graph(思维简单题)

HDU 6228 tree 简单思维树dp

hdu2094—看似拓扑实际上是一道思维题

HDU - 4793 思维计算几何直线和圆交点

HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)