Select HDU - 5101 (理解lower_bound)

这道题是一道关于二分查找或者lower_bound的习题,不多说,先来看题:

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.
InputThere is a number T shows there are T test cases below. ( T20T≤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 (  0n10000≤n≤1000 ), k(  0k<2310≤k<231 ). 
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(  0m1000≤m≤100 ), v[i](  0v[i]<2310≤v[i]<231 )OutputFor each test case, output a single integer.Sample Input
1
3 1
1 2
1 2
2 1 1
Sample Output
5

当然,这道题我Run Time Error好多次之后终于A掉了,对于这道题的RT并非算法问题,仔细检查发现,只是结构体内数组开小了。

接下来讲一下这道题的具体思路:

        面对这道题,为什么会想到用lower_bound?(不看题解的话)  因为这里的小男孩要找的是喝智商比他高的两名队友,我的想法就是,我们先提一个“预定队友”出来,那么,我们只需要找到那些大于“k-预定队友的IQ”的值的学生就好,但是一对对找绝对会T(本人亲自操作,绝对会T),此时的复杂度为O(n*m*log(n*m)),这时,我想到的是,怎么把复杂度中的那个n或者m去掉那么就有可能a了,那么怎么去掉呢?以下是我的思路:

        我们从1到n记录每一个班级,用结构体中的数组记录每一位同学的IQ,那么加入有一个“大班级”保留了所有学生的IQ然后我们去这个大班级里用lower_bound找有多少个学生符合要求岂不是可以省去“*m”的时间,然而,这个操作却会使得数据偏大,为什么呢?因为,其中一部分学生是自己班级的,我们不能带他们一起去!但是如果这样去掉这些人,我们又会发现:好像是我们想的简单了,我们开出来的answer刚好是正解的2倍,因为这是个组合而不是排列,他不该有顺序性,所以“/2”就是使得那些被二次计算的学生排除。

附上AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n,k;
struct node
{
    ll n;
    ll id[100005];
}v[1005];
ll sum=0;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        sum=0;
        scanf("%lld %lld%*c",&n,&k);
        v[0].n=0;
        for(ll i=1,l=0;i<=n;i++)
        {
            scanf("%lld",&v[i].n);
            for(ll j=0;j<v[i].n;j++)
            {
                scanf("%lld",&v[i].id[j]);
                v[0].id[l++]=v[i].id[j];
            }
            scanf("%*c");
            v[0].n+=v[i].n;
            sort(v[i].id, v[i].id+v[i].n);
            v[0].n=l;
        }
        sort(v[0].id, v[0].id+v[0].n);
        for(ll i=1;i<=n;i++)
        {
            for(ll j=0;j<v[i].n;j++)
            {
                ll x=v[i].id[j];
                ll ans1=v[0].n-(lower_bound(v[0].id, v[0].id+v[0].n, k-x+1)-v[0].id);
                ll ans2=v[i].n-(lower_bound(v[i].id, v[i].id+v[i].n, k-x+1)-v[i].id);
                sum+=ans1-ans2;
            }
        }
        printf("%lld\n",sum/2);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/80470666