hihoCoder 1236 Scores(bitset+分块)

这篇博客介绍了hihoCoder 1236题目的解题思路,采用分块技术和bitset来高效处理5维数据。通过对每维数据进行sqrt(n)长度的分块,使用bitset存储每个块的元素状态。在查询时,通过二分查找确定位置,并计算5维结果的按位与操作。
摘要由CSDN通过智能技术生成

题目链接:hihoCoder 1236 Scores

解题思路

将5维分开考虑,对于每一维,将n分成sqrt(n)长度为一块,用bitset维护,S[i]表示0~i这些中包含的元素id。对于每次查询,用二分找到对应为值,处理出对应的二进制位。然后5维结果取且。

代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <bitset>
#include <vector>
#include <algorithm>

using namespace std;
typedef pair<int,int> pii;
const int maxn = 5 * 1e4 + 5;
const int maxm = 300 + 5;

int N, M, Q, L[maxm], R[maxm], B[maxn];
pii scores[5][maxn];
bitset<50005> S[5][300], A[10];

void init () {
    scanf("%d%d", &N, &M);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < 5; j++) {
            scanf("%d", &scores[j][i].first);
            scores[j][i].second = i;
        }
    }

    int len = sqrt(N);
    int block = N / len + (N % len ? 1 : 0);
    L[0] = R[0] = -1;
    for (int i = 1; i <= block; i++) {
        L[i] = (i-1) * len;
        R[i] = i * len;
    }
    R[block] = N;

    for (int i = 0; i < 5; i++)
        S[i][0] = 0;

    for (int i = 0; i < 5; i++) {
        sort(scores[i], scores[i] + N);
        for (int j = 1; j <= block; j++) {
            S[i][j] = S[i][j-1];
            for (int k = L[j]; k < R[j]; k++)
                S[i][j][scores[i][k].second] = 1;
        }
    }

    for (int i = 1; i <= block; i++) {
        for (int j = L[i]; j < R[i]; j++)
            B[j] = i;
    }
}

void solve (int u, int x) {
    int t = lower_bound(scores[u], scores[u] + N, make_pair(x, N)) - scores[u];
    //printf("%d %d!!!!\n", t, B[t]);
    A[u] = S[u][B[t]-1];
    for (int i = L[B[t]]; i < t; i++) {
        A[u][scores[u][i].second] = 1;
    //  printf("%d\n", scores[u][i].second);
    }
}

int main () {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        init();

        int bw = 0, x;
        scanf("%d", &Q);
        while (Q--) {
            for (int i = 0; i < 5; i++) {
                scanf("%d", &x);
                solve(i, x^bw);
            }
            for (int i = 4; i; i--)
                    A[i-1] &= A[i];
            bw = A[0].count();
            printf("%d\n", bw);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值