[hdu5101]计数问题

http://acm.hdu.edu.cn/showproblem.php?pid=5101

题目大意:给n个集合,求从两个不同集合里面各取一个数使得它们的和大于给定数的方案数。

ans=从所有数里面取两个数的方案数-从每个集合里面取两个数的方案数(这是关键)


如果不转换也可以这么做,离散一下,然后树状数组统计也行,具体见代码。

代码一:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <map>
 7 #include <vector>
 8 #include <stack>
 9 #include <string>
10 #include <ctime>
11 #include <queue>
12 #define mem0(a) memset(a, 0, sizeof(a))
13 #define mem(a, b) memset(a, b, sizeof(a))
14 #define lson l, m, rt << 1
15 #define rson m + 1, r, rt << 1 | 1
16 #define eps 0.0000001
17 #define lowbit(x) ((x) & -(x))
18 #define memc(a, b) memcpy(a, b, sizeof(b))
19 #define x_x(a) ((a) * (a))
20 #define LL long long
21 #define DB double
22 #define pi 3.14159265359
23 #define MD 10000007
24 #define INF (int)1e9
25 #define max(a, b) ((a) > (b)? (a) : (b))
26 using namespace std;
27 int b[110000];
28 LL solve(int a[], int n, int x)
29 {
30         LL ans = 0;
31         for(int i = 1; i <= n; i++) {
32                 int tmp = upper_bound(a + 1, a + 1 + n, x - a[i]) - a;
33                 ans += n - tmp + 1;
34         }
35         return ans;
36 }
37 int main()
38 {
39         //freopen("input.txt", "r", stdin);
40         //freopen("output.txt", "w", stdout);
41         int n, k, T;
42         cin>> T;
43         while(T--) {
44                 cin>> n>> k;
45                 LL ans1 = 0, ans2 = 0;
46                 int tot = 0;
47                 for(int i = 1; i <= n; i++) {
48                         int m, a[110];
49                         cin>> m;
50                         for(int j = 1; j <= m; j++) {
51                                 scanf("%d", &a[j]);
52                                 b[++tot] = a[j];
53                         }
54                         sort(a + 1, a + 1 + m);
55                         ans1 += solve(a, m, k);
56                 }
57                 sort(b + 1, b + 1 + tot);
58                 ans2 = solve(b, tot, k);
59                 cout<< (ans2 - ans1) / 2<< endl;
60         }
61         return 0;
62 }
View Code

代码二(树状数组):

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <map>
  7 #include <vector>
  8 #include <stack>
  9 #include <string>
 10 #include <ctime>
 11 #include <queue>
 12 #define mem0(a) memset(a, 0, sizeof(a))
 13 #define mem(a, b) memset(a, b, sizeof(a))
 14 #define lson l, m, rt << 1
 15 #define rson m + 1, r, rt << 1 | 1
 16 #define eps 0.0000001
 17 #define lowbit(x) ((x) & -(x))
 18 #define memc(a, b) memcpy(a, b, sizeof(b))
 19 #define x_x(a) ((a) * (a))
 20 #define LL long long
 21 #define DB double
 22 #define pi 3.14159265359
 23 #define MD 10000007
 24 #define INF (int)1e9
 25 #define max(a, b) ((a) > (b)? (a) : (b))
 26 using namespace std;
 27 map<int, int> hash;
 28 int nn, tot, arr[220000], arr0[220000], c[220000], a[1200][120], m[1200];
 29 void init()
 30 {
 31         sort(arr + 1, arr + 1 + tot);
 32         arr0[1] = arr[1];
 33         nn = 1;
 34         hash[arr0[1]] = 1;
 35         for(int i = 2; i <= tot; i++) {
 36                 if(arr[i] != arr[i - 1]) {
 37                         arr0[++nn] = arr[i];
 38                         hash[arr[i]] = nn;
 39                 }
 40         }
 41 }
 42 void update(int p, int x)
 43 {
 44         while(p <= nn) {
 45                 c[p] += x;
 46                 p += lowbit(p);
 47         }
 48 }
 49 void insert(int a[], int n)
 50 {
 51         for(int i = 1; i <= n; i++) {
 52                 int tmp = hash[a[i]];
 53                 update(tmp, 1);
 54         }
 55 }
 56 int sum(int p)
 57 {
 58         int ans = 0;
 59         while(p) {
 60                 ans += c[p];
 61                 p -= lowbit(p);
 62         }
 63         return ans;
 64 }
 65 int query(int L, int R)
 66 {
 67         return sum(R) - sum(L - 1);
 68 }
 69 int find(int x)
 70 {
 71         int l = 1, r = nn;
 72         while(l < r) {
 73                 int m = (l + r) >> 1;
 74                 if(arr0[m] > x) r = m;
 75                 else l = m + 1;
 76         }
 77         return l;
 78 }
 79 int main()
 80 {
 81         //freopen("input.txt", "r", stdin);
 82         //freopen("output.txt", "w", stdout);
 83         int T;
 84         cin>> T;
 85         while(T--) {
 86                 hash.clear();
 87                 mem0(c);
 88                 int n, k;
 89                 cin>> n>> k;
 90                 tot = 0;
 91                 for(int i = 1; i <= n; i++) {
 92                         cin>> m[i];
 93                         for(int j = 1; j <= m[i]; j++) {
 94                                 scanf("%d", &a[i][j]);
 95                                 arr[++tot] = a[i][j];
 96                         }
 97                 }
 98                 init();
 99                 insert(a[1], m[1]);
100                 LL ans = 0;
101                 for(int i = 2; i <= n; i++) {
102                         for(int j = 1; j <= m[i]; j++) {
103                                 int tmp = find(k - a[i][j]);
104                                 ans += query(tmp, nn);
105                         }
106                         insert(a[i], m[i]);
107                 }
108                 cout<< ans<< endl;
109         }
110         return 0;
111 }
View Code

 

posted @ 2014-11-13 15:52  jklongint  阅读(243)  评论(0编辑  收藏  举报