HDU 5101 Select(不同集合的两个数大于k的方案数)

Select

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1422    Accepted Submission(s): 395

Problem Description

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≤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≤1000 ),
k( 0≤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( 0≤m≤100 ),
v[i]( 0≤v[i]<231 )

Output

For each test case, output a single integer.

Sample Input

1
3 1
1 2
1 2
2 1 1

Sample Output

5

Source

BestCoder Round #17

题目大意:给出n个集合,每个集合有m个数,不同的集合,m的值不一定相同,问从不同的集合中取两个数,使得这两个数的和大于k的取法有多少种。

解题思路:

对于一组有m个数,如果要取两个数a和b,使得这两个数的和大于k,那么可以将这组数由小到大排序,然后枚举a,查找满足条件的数b的个数,在查找数b的个数时,可以利用lower_bound函数(二分查找)。比如:我们找到第一个满足a+b>k的b是第i个数,则第i+1,i+2,……个数都满足。枚举a的过程记数并加和,得到的结果就是满足条件的(a,b)对的2倍。

题目要求不同的集合,可以利用总集合中满足条件的数对 - 相同集合满足条件的集合数对。

(注意:单个集合的数最多有100,集合数目最多有1000,则总集合的数最多有100000)

代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-6)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
struct IQ
{
    ll m;
    ll v[100005];
}a[1005];
int main()
{
    ll i,j,l,m,n,v,k,t;
    scanf("%I64d",&t);
    while(t--)
    {
        scanf("%I64d%I64d",&n,&k);
        a[0].m=0;
        for(i=1,l=0;i<=n;i++)
        {
            scanf("%I64d",&m);
            a[i].m=m;
            a[0].m+=m;
            for(j=0;j<m;j++)
            {
                scanf("%I64d",&v);
                a[i].v[j]=v;
                a[0].v[l++]=v;
            }
            sort(a[i].v,a[i].v+m);
        }
        sort(a[0].v,a[0].v+a[0].m);
        ll ans=0;
        for(i=1;i<=n;i++)
        {
            for(j=0;j<a[i].m;j++)
            {
                v=a[i].v[j];
                ll x=lower_bound(a[0].v,a[0].v+a[0].m,k-v+1)-a[0].v;
                ll n1=a[0].m-x;
                //printf("i=%I64d j=%I64d x=%I64d n1=%I64d    ",i,j,x,n1);
                ll y=lower_bound(a[i].v,a[i].v+a[i].m,k-v+1)-a[i].v;
                ll n2=a[i].m-y;
                //printf("i=%I64d j=%I64d y=%I64d n2=%I64d\n",i,j,y,n2);
                ans+=n1-n2;
            }
        }
        printf("%I64d\n",ans/2);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-16 20:04:40

HDU 5101 Select(不同集合的两个数大于k的方案数)的相关文章

hdu 5101 Select

http://acm.hdu.edu.cn/showproblem.php?pid=5101 在比赛的时候没有想出怎么做,自己真水. 题意:给定一些集合,选择两个来自不同集合的数,加和大于k,问有多少种选择方案. 思路:答案=从所有数中选择的两个加和大于k的数的方案数-在同一个集合中选择的两个加和大于k的数的方案数而对于同一个集合中选择的两个加和大于k的方案数是可以直接排序然后利用单调性快速统计出来的.利用vector把所有的数存到q[0]里面.对q[0]排序,也对q[i]排序. 然后在q[0]

hdu 5101 Select(Bestcoder Round #17)

Select                                                    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 285    Accepted Submission(s): 85 Problem Description One day, Dudu, the most clever bo

编程题:返回指针值的函数,求两个数中较大的数。

#include<stdio.h> int *max(int *x,int *y) { int *q; if(*x>*y)  q=x; else  q=y; return q; } void main() { int a,b,*p; scanf("%d,%d",&a,&b); p=max(&a,&b); printf("%d,%d,max is %d\n",a,b,*p); } 编程题:返回指针值的函数,求两个数中较

编程题:指向函数的指针,求两个数中较大的数。

#include<stdio.h> int max(x,y) { int z; if(x>y)  z=x; else  z=y; return z; } void main() { int a,b,c; int (*p)(); p=max; scanf("%d,%d",&a,&b); c=(*p)(a,b); printf("%d,%d,max is %d\n",a,b,c); } 编程题:指向函数的指针,求两个数中较大的数.,布布

hdu 5101 Select(树状数组)

题目链接:hdu5101 Select 题目大意:N和K,给定若干组数,要从从不同组中选出连个数和大于K,问说有多少种组成方案. 解题思路:树状数组维护,将所有的数离散化掉对应成树状数组的下标,每次先计算一组,然后再将该组的元素插入到 树状数组中. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int m

hdu 5101 Select (二分+单调)

题意: 多多有一个智商值K. 有n个班级,第i个班级有mi个人.智商分别是v1,v2,.....vm. 多多要从这些人中选出两人.要求两人智商和大于K,并且两人不同班.问总共有多少种方案. 数据范围: n ( 0≤n≤1000 ), k( 0≤k<2^31 ) m( 0≤m≤100 ), v[i]( 0≤v[i]<2^31 ) 思路: 对于一个单调长的序列,可以很容易地统计两数之和大于K的对数(枚举第一个数,二分找到满足条件的最小的数的位置,然后它和它后面的数都是满足条件的) 故对于每个班内,

HDU 5101 Select --离散化+树状数组

题意:n 组,每组有一些值,求 在不同的两组中每组选一个使值的和大于k的方法数. 解法:n * Cnt[n] <= 1000*100 = 100000, 即最多10^5个人,所以枚举每个值x,求他的后面那些组中有多少数大于 k-x即可, 求有多少数大于k-x可以先求有多少数小于等于k-x,然后总数减一下即可. 可以用树状数组求. 先把所有数离散地存入一个树状数组中,然后每次枚举完一组的数后,将这组的数去掉. 代码: #include <iostream> #include <cst

和为s的两个数,一串连续数 41

? ? 引言 ? ? 第一问题很简单,leetcode上也有相应的题,2Sum问题,leetcode上还有2Sum的进阶版3Sum,只是在这个问题上增加了一层循环而已,另外还有3Sum_Close问题,就是和接近s的三个数,本文将依次介绍2Sum问题,3Sum问题,以及3Sum_close,以及一串连续数问题 ? ? 对于3Sum的问题,本文除了常用的退化为2Sum的n平方的解法外,还提供了一种hash的方法,使得利用hash的方法使得4Sum问题不再是n三次方的时间复杂度,可以降到n平方的时间

C语言笔试题精选1---求两个数之间较大的数,不使用if、while、switch、for、?:/以及任何比较语句

题目:求两个数a.b之间较大的数,不使用if.while.switch.for.?:/以及任何比较语句 #include <stdio.h> int min(int a, int b) { int d = a - b; int flag = ((unsigned int)d) >> 31; int array[] = {b, a}; return array[flag]; } int main(int argc, char *argv[]) { int i_min, a, b; s