• hihocoder #1236 Scores (15北京赛区网络赛J) (五维偏序,强制在线,bitset+分块)


    链接:http://hihocoder.com/problemset/problem/1236

    思路;

    有n个五维的向量,给出q个询问,每个询问是一个五维向量,问有多少个向量没有一维比这个向量大。并且答案需要加密,除了第一个答案,其他答案都要和上一个答案异或。

    因为是强制在线所以不能用cdq分治写。。我们可以用stl里面的bitset来写这道题,但是因为数据还是太大了,这里我们可以用分块处理下,降低空间复杂度,需要用的时候直

    接二分查找需要的块,预处理后可以o(1)获取前k-1个块的信息,然后我们对当前块逐个更新下就好了。

    这里 bit[i][j]代表第i维前j个块有多少个人。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 5e4+10;
    
    struct node{
        int val,id;
        node(){};
        node(int val,int id):val(val),id(id){}
        bool operator < (const node &b) const{
            if(val == b.val) return id < b.id;
            return val < b.val;
        }
    }a[6][M];
    bitset<M>bit[6][300];
    bitset<M>ans;
    bitset<M>temp;
    int block;
    int num;
    
    int main()
    {
        int t,n,m,q;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            for(int i = 1;i <= n;i ++)
                for(int j = 1;j <= 5;j ++)
                    scanf("%d",&a[j][i].val),a[j][i].id = i;
    
            for(int i = 1;i <= 5;i ++) sort(a[i]+1,a[i]+n+1);
            block = sqrt(n);
            //分块,预处理
            for(int i = 1;i <= 5;i ++){
                for(int j = 1;(j-1)*block < n;j ++){
                    bit[i][j].reset();
                    bit[i][j] = bit[i][j-1];
                    int st = (j-1)*block;
                    for(int k = 1;k <= block&&st+k<=n;k ++){
                        bit[i][j].set(a[i][st+k].id);
                    }
                }
            }
            
            int q;
            scanf("%d",&q);
            int now[6];
            int pre = 0;
            while(q--){
                for(int i = 1;i <= 5;i ++){
                    scanf("%d",&now[i]);
                    now[i]^=pre;
                }
                ans.reset();
                for(int i = 1;i <= 5;i ++){
                    int tmp = lower_bound(a[i]+1,a[i]+n+1,node(now[i],n+1))-a[i]-1;
                    tmp = tmp/block;
                    temp = bit[i][tmp];//获取之前块的信息
                    for(int j = tmp*block+1;a[i][j].val<=now[i]&&j<=n;j++){ //当前块这个更新
                        temp.set(a[i][j].id);
                    }
                    if(i == 1)
                        ans = temp;
                    else
                        ans &= temp;
                }
                int num = ans.count();
                pre = num;
                printf("%d
    ",num);
            }
        }
        return 0;
    }
  • 相关阅读:
    从头认识java-17.4 具体解释同步(2)-具体解释竞争条件
    ProgressBar的indeterminateDrawable属性在安卓6.0上的问题
    Android开源-NineOldAndroids
    面向对象语言的多态性问题
    Android Data Binding代码实践(告别findViewById)(四)
    【c语言】将正数变成相应的负数,将负数变成相应的正数
    Android 消息处理源代码分析(2)
    怎样学习嵌入式软件
    C++ regex
    C++中两个类相互include的问题
  • 原文地址:https://www.cnblogs.com/kls123/p/9506850.html
Copyright © 2020-2023  润新知