Gym - 100203A Ariel 暴力+位运算

题意:第i种生物有k[i]个特征,分数是score[i],现在要参加竞赛,报出一种生物a,和一些特征h[i],参加竞赛的所有生物在这些h[i]上面的特征是一样的,a生物有h[i],则所有竞赛的生物都必须有h[i],a生物没有,竞赛的生物也没有,没有提到的则不用管。问你在竞赛中a的排名

思路:特征最多只有10中,所有可以用二进制的每一位表示特征的状态,并记录下每种状态下的生物的类型。现在给你生物的状态,首先要求出能参加竞赛的生物的种类。当 (i&p == t[a]&p) 时,所有拥有i状态的生物就是可以参加竞赛的。再用二分找到在这些类型中a的位置,加起来便是排名了

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <fstream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <deque>
 7 #include <vector>
 8 #include <queue>
 9 #include <string>
10 #include <cstring>
11 #include <map>
12 #include <stack>
13 #include <set>
14 #define LL long long
15 #define eps 1e-8
16 #define INF 0x3f3f3f3f
17 #define MAXN 10005
18 using namespace std;
19 int G[1100][MAXN];
20 int s[MAXN], t[MAXN];
21 vector<int> f[1100];
22 int main()
23 {
24 #ifndef ONLINE_JUDGE
25     freopen("in.txt", "r", stdin);
26     //freopen("out.txt", "w", stdout);
27 #endif // OPEN_FILE
28     int n, k, m;
29     scanf("%d%d", &n, &k);
30     int x, y, p;
31     for(int i = 0; i < 1025; i++){
32         G[i][0] = 0;
33     }
34     for(int i = 1; i <= n; i++){
35         scanf("%d%d", &s[i], &y);
36         p = 0;
37         for(int j = 1; j <= y; j++){
38             scanf("%d", &x);
39             p |= 1 << (x - 1);
40         }
41         f[p].push_back(s[i]);
42         t[i] = p;
43         G[p][0]++;
44         G[p][G[p][0]] = s[i];
45     }
46     for(int i = 0; i <= 1025; i++){
47         sort(G[p], G[p] + G[p][0]);
48         sort(f[i].begin(), f[i].end());
49     }
50     scanf("%d", &m);
51     int q;
52     int ans;
53     for(int i = 1; i <= m; i++){
54         scanf("%d%d", &x, &y);
55         p = 0;
56         for(int j = 1; j <= y; j++){
57             scanf("%d", &q);
58             p |= 1 << (q - 1);
59         }
60         ans = 1;
61         for(int i = 0; i <= 1025; i++){
62             if((i & p) != (t[x] & p))continue;
63             ans += f[i].size() - (upper_bound(f[i].begin(), f[i].end(), s[x]) - f[i].begin());
64             continue;
65             int left = 1, right = G[i][0];
66             while(left < right){
67                 int mid = (left + right) >> 1;
68                 if(G[i][mid] > s[x]){
69                     right = mid;
70                 }
71                 else{
72                     left = mid + 1;
73                 }
74             }
75             if(G[i][left] == s[x]) continue;
76             //ans += left - 1;
77             //continue;
78             if(G[i][left] > s[x]){
79                 ans += left;
80             }
81             else if(G[i][left] < s[x]){
82                 ans += left - 1;
83             }
84             //ans += left;
85             //if(G[i][left] == s[x])
86             //ans += left -1;
87         }
88         printf("%d\n", ans);
89     }
90 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值