• hihocoder1236(北京网络赛J):scores 分块+bitset


    北京网络赛的题- -。当时没思路,听大神们说是分块+bitset,想了一下发现确实可做,就试了一下,T了好多次终于过了

    题意:

    初始有n个人,每个人有五种能力值,现在有q个查询,每次查询给五个数代表查询的五种能力值,输出有多少个人每种能力值都比查询的小

    n和q都是50000,每种能力值最大也为50000

    思路:

    对于某一个大小的能力值,有哪些人的此项能力值比他小可以用一个50000的bitset表示。这样我们在查询的时候就可以拿到5个对应的bitset,对其进行and就可以得出最终的人数

    这样每组询问的复杂度为5*n/32 总复杂度较高但勉强可以接受。

    但是这样做有一点问题就是要开5*50000个大小为50000的bitset,显然这样会超内存。。于是想到将bitset分块,这样虽然询问时需要花费一定时间(sqrt)来找到5个bitset

    但是显然这个时间是小于n/32的,所以并不会对总时间造成较大的影响,于是显然可行

    注意一点就是分块的时候不仅要按照分数段分块,还要按照人数分块,否则如果某个分数段人数太多就gg了

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 bitset<50010>b[7][500];
     4 bitset<50010>tmp;
     5 int n,m,q;
     6 int a[50010][7];
     7 vector<int>v[7][50010];
     8 bitset<50010>p[7];
     9 int tt=10;
    10 int now[5];
    11 vector<int>d[7];
    12 int main()
    13 {
    14     //freopen("in.txt","r",stdin);
    15     int T;
    16     scanf("%d",&T);
    17     while(T--)
    18     {
    19         scanf("%d%d",&n,&m);
    20         for(int i=0; i<5; i++)
    21         {
    22             d[i].clear();
    23             for(int j=1; j<=m; j++)
    24             {
    25                 v[i][j].clear();
    26             }
    27         }
    28         for(int i=0;i<5;i++)
    29         {
    30             for(int j=1;j<=300;j++)
    31             {
    32                 b[i][j].reset();
    33             }
    34         }
    35         for(int i=0; i<n; i++)
    36         {
    37             for(int j=0; j<5; j++)
    38             {
    39                 scanf("%d",a[i]+j);
    40                 v[j][a[i][j]].push_back(i);
    41             }
    42         }
    43         int tm=0;
    44         for(int i=0; i<5; i++)
    45         {
    46             tm=0;
    47             tmp.reset();
    48             b[i][0]=tmp;
    49             d[i].push_back(0);
    50             for(int j=0; j<=m; j++)
    51             {
    52                 for(int to:v[i][j])
    53                 {
    54                     tmp[to]=1;
    55                     tm++;
    56                 }
    57                 if(tm>sqrt(n)||j-d[i][(int)d[i].size()-1]>sqrt(m)||j==m)
    58                 {
    59                     b[i][(int)d[i].size()]=tmp;
    60                     d[i].push_back(j);
    61                     tm=0;
    62                 }
    63             }
    64         }
    65         scanf("%d",&q);
    66         int pre=0;
    67         tm=0;
    68         while(q--)
    69         {
    70             for(int i=0; i<5; i++)
    71             {
    72                 scanf("%d",now+i);
    73                 now[i]^=pre;
    74             }
    75             for(int i=0; i<5; i++)
    76             {
    77                 int kk=upper_bound(d[i].begin(),d[i].end(),now[i])-d[i].begin();
    78                 kk--;
    79                 p[i]=b[i][kk];
    80                 for(int j=d[i][kk]+1; j<=now[i]; j++)
    81                 {
    82                     for(int to:v[i][j])
    83                     {
    84                         p[i][to]=1;
    85                     }
    86                 }
    87                 //p&=tmp;
    88             }
    89             for(int i=1;i<5;i++)
    90             {
    91                 p[0]&=p[i];
    92             }
    93             int ans=p[0].count();
    94             pre=ans;
    95             printf("%d
    ",ans);
    96         }
    97     }
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    选择最佳服务台方案的7个考量
    使用OpManager轻松进行Windows网络监控
    统一终端管理(UEM)有哪些关键的安全功能
    javascript的声明变量var,let,const的区别
    Vue 在过滤器filter中调用methods中的方法
    第十六章:过滤器的奥秘
    1970年1月1日(00:00:00 GMT)Unix 时间戳(Unix Timestamp)
    让网页中的JavaScript代码自动执行的三种方法
    限制input type=“file“ 文件上传类型
    对v-html的文字做超出显示省略号
  • 原文地址:https://www.cnblogs.com/oneshot/p/4831731.html
Copyright © 2020-2023  润新知