2015北京网络赛 J Scores bitset+分块

2015北京网络赛 J Scores

题意:50000组5维数据,50000个询问,问有多少组每一维都不大于询问的数据

思路:赛时没有思路,后来看解题报告也因为智商太低看了半天看不懂。bitset之前没用过,查了下发现其实就是一个二进制表示,这里的每一位就表示原序中的状态。

    建一个bitset<50000> bs[6][sqrt(50000)], bs[i][j] 就表示在第i维上前j个块中的数据在原序中是哪些位置。

  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 #include <bitset>
 15 #define LL long long
 16 #define eps 1e-8
 17 #define INF 0x3f3f3f3f
 18 #define MAXN 50005
 19 using namespace std;
 20 struct Node{
 21     int x, pos;
 22 };
 23 bitset<MAXN> bs[6][230];
 24 int t[6];
 25 bitset<MAXN> res[6], w;
 26 bool compare(Node a, Node b){
 27     return a.x < b.x;
 28 }
 29 Node s[6][MAXN];
 30 int main()
 31 {
 32 #ifndef ONLINE_JUDGE
 33     freopen("in.txt", "r", stdin);
 34     //freopen("out.txt", "w", stdout);
 35 #endif // OPEN_FILE
 36     int T;
 37     int n, m;
 38     scanf("%d", &T);
 39     while (T--){
 40         scanf("%d%d", &n, &m);
 41         for (int i = 1; i <= n; i++){
 42             for (int j = 1; j <= 5; j++){
 43                 scanf("%d", &s[j][i].x);
 44                 s[j][i].pos = i;
 45             }
 46         }
 47         for (int i = 1; i <= 5; i++){
 48             sort(s[i] + 1, s[i] + 1 + n, compare);
 49         }
 50         int u = sqrt(n);
 51         int num = n / u;
 52         if (n % u != 0){
 53             num++;
 54         }
 55         memset(bs, 0, sizeof(bs));
 56         for (int i = 1; i <= 5; i++){
 57             for (int j = 1;j <= num; j++){
 58                 bs[i][j] |= bs[i][j - 1];
 59                 int left = (j - 1) * u + 1, right = j * u;
 60                 if (right > n){
 61                     right = n;
 62                 }
 63                 for (int k = left; k <= right; k++){
 64                     bs[i][j][s[i][k].pos] = 1;
 65                 }
 66             }
 67         }
 68         int ans = 0;
 69         int q;
 70         scanf("%d", &q);
 71         while (q--){
 72             for (int i = 1; i <= 5; i++){
 73                 scanf("%d", &t[i]);
 74                 t[i] ^= ans;
 75             }
 76             for (int i = 1; i <= 5; i++){
 77                 int left = 1, right = n;
 78                 while (left < right){
 79                     int mid = (left + right) >> 1;
 80                     if (s[i][mid].x > t[i]){
 81                         right = mid;
 82                     }
 83                     else{
 84                         left = mid + 1;
 85                     }
 86                 }
 87                 int pos;
 88                 if (s[i][left].x > t[i]){
 89                     pos = left - 1;
 90                 }
 91                 else{
 92                     pos = left;
 93                 }
 94                 int u_pos = (pos - 1) / u;
 95                 res[i] = bs[i][u_pos];
 96                 for (int j = u_pos * u + 1; j <= pos; j++){
 97                     res[i][s[i][j].pos] = 1;
 98                 }
 99             }
100             w = res[1];
101             for (int i = 2; i <= 5; i++){
102                 w &= res[i];
103             }
104             ans = w.count();
105             printf("%d\n", ans);
106         }
107     }
108 }

 

posted on 2015-09-25 11:47  张济  阅读(166)  评论(0编辑  收藏  举报

导航