首页 > 其他 > 详细

BestCoder17 1002.Select(hdu 5101) 解题报告

时间:2014-11-12 22:56:55      阅读:359      评论:0      收藏:0      [点我收藏+]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5101

题目意思:给出 n 个 classes 和 Dudu 的 IQ(为k),每个classes 都有相应的人,每个人又有相应的IQ。现在要求从这些classes挑选两个人,满足IQ之和 > k,不过要满足这两个人不能来自同一个class的。

    解题思路不难想出,直接所有人两两之和 > k - 同一个class 两两之和 > k  就是答案了。

不过很容易超时!!!!

    用二分就可以过了。二分有两个STL函数:lower_bound 和 upper_bound。这里用到lower_bound,它一般是跟vector一起用的。看了好久终于看懂了= =,十分强大~~~呀!如果大家对这两个函数比较熟悉,可以直接略过以下注释内容(只结合自己的理解说一下lower_bound,可能有误导他人成分,希望大家多多包涵)。共同的一点就是都需要对操作数组进行排序。

/********************************************************

    假设有vector<int> q,第三个参数假设用key来表示。

  lower_bound(q.begin(), q.end(), key) 这个东西并不是返回一个int数值,而是vector<int>::iterator vit,假设vit = lower_bound(q.begin(), q.end(), key)(这样为了方便解说)。但是如果 vit - q.begin(),返回的是 >= key 且从左到右开始数起的第一个元素下标(int 数值),其实就是插入key的位置,如果这个数组中有和key相等的数,就插入跳过所有和key相同的数的下一位置(结合下面例子中的key = 10来看)。如果 q.end() - vit 返回的是 >= key 且从右数起的第一个元素的下标(i),但满足下标i-1 这个数是 < key的。至于 *vit 就是具体指向的数值啦,不是下标!

    例如有 4,10,10,30,69,70,96,100(第一个元素下标从0开始)

              vit - q.begin()        q.end() - vit       

     key = 9,             1                          7

     key = 10              3(不是1,注意)           5

     *****************************************/

     接着结合思路来讲,先给出一组数据:

   1

      3   3

      3   5   2   7

      2   1   9

      3   4   2   6

    我们声明一个vector<int> p[maxn],p[0] 压入所有人的IQ ,p[i]压入对应第 i 个班里所有人的IQ,然后对p[0]~p[n] 从小到大排序(有n个class,但还有一个包含所有class的p[0])。

处理完之后 p[0]:  1   2   2   4   5   6   7   9

           p[1]:  2   5   7

           p[2]:   1   9

           p[3]:   2   4   6

    然后遍历每个class的人,假如从p[1] 的 2(用v来表示) 开刀。

  LL num1 = p[0].end() - lower_bound(p[0].begin(), p[0].end(), k-v+1);

    表示 >= k-v+1 从右开始数 >= (3-2+1) 的数的下标,但前一个数必须要 < 2,那么就是p[0]中数组下标为1,表示 2 这个数,跟 2,4,5,6,7,9 这些数相加可以 > k。p[1]同理。之后要相减保存到ans中。但ans 最终要除以2才是答案(这个...我也纠结了好久)

    举个例子就明白了。

    例如处理到6,那么 k-v+1变成负数了,返回的是数组下标 0,就是表示 6 跟其他所有数两两相加都满足 > k,有1+6,2+6,....6+7,6+9;处理到7的时候,也是返回数组下标0,于是有1+7, 2+7,...,6+7, 7+9。  6+7被选了两次!!!!所以要除以2!

    最后一点就是记得将vector清空啦~~~~

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 using namespace std;
 8 
 9 #define pb push_back
10 typedef __int64 LL;
11 const int maxn = 1000 + 10;
12 vector<int> p[maxn];
13 
14 int main()
15 {
16     #ifndef ONLINE_JUDGE
17         freopen("ljy.txt", "r", stdin);
18     #endif
19 
20     int T, n, k, m, input;
21     while (scanf("%d", &T) != EOF)
22     {
23         while (T--)
24         {
25             p[0].clear();
26             scanf("%d%d", &n, &k);
27             for (int i = 1; i <= n; i++)
28             {
29                 scanf("%d", &m);
30                 p[i].clear();
31                 for (int j = 0; j < m; j++)
32                 {
33                     scanf("%d", &input);
34                     p[i].pb(input);
35                     p[0].pb(input);
36                 }
37                 sort(p[i].begin(), p[i].end());
38             }
39             sort(p[0].begin(), p[0].end());
40 
41             LL ans = 0;
42             for (int i = 1; i <= n; i++)
43             {
44                 for (int j = 0; j < p[i].size(); j++)
45                 {
46                     int v = p[i][j];
47                     LL num1 = p[0].end() - lower_bound(p[0].begin(), p[0].end(), k-v+1);
48                     LL num2 = p[i].end() - lower_bound(p[i].begin(), p[i].end(), k-v+1);
49                     ans += num1 - num2;
50                 }
51             }
52             printf("%I64d\n", ans >> 1);
53         }
54     }
55     return 0;
56 }

 

    

BestCoder17 1002.Select(hdu 5101) 解题报告

原文:http://www.cnblogs.com/windysai/p/4093678.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!