hihocoder 1236 (分块+bitset乱搞)

来源:互联网 发布:卓文网络商学院 编辑:程序博客网 时间:2024/06/04 22:54

Kyle is a student of Programming Monkey Elementary School. Just as others, he is deeply concerned with his grades.

Last month, the school held an examination including five subjects, without any doubt, Kyle got a perfect score in every single subject.

There are n students took part in this examination(not including Kyle), and everyone got an integer between 1 to m as the score of one subject.

Now, looking at the grade table of these n students, Kyle wants to know how many students still did no better than him even if his scores are something else – Here, “no better” means there is no subject in which the student got strictly greater score than Kyle.

Input
There are multiple test cases.

The first line of the input contains an integer T (T <= 3) which means the number of test cases.

The first line of each test case contains two integers, n, m(n, m≤ 50,000), which are the number of students and the perfect score of each subject.

In the next n lines, each line consists of five integers, indicating a student’s scores.

Then one line follows. This line contains an integer q(q≤ 50,000) indicating the number of queries.

In the next q lines, each line contains five integers as well, representing a query. Each query indicates a set of scores, and for each query, you should figure out that if Kyle’s grade is this set of scores, how many students still did no better than him. But for the sake of security, only the first query is in its original form, and other queries are encrypted. To decrypt a query, you must let each integer in the query do xor operation with the answer of last query. It’s guaranteed that all the decrypted queries contain integers between 1 and 50000.

Output
For each test case, you should output q lines as the answer for all queries.

Sample Input
2
2 3
1 1 1 1 1
2 2 2 2 2
2
1 1 1 1 1
3 3 3 3 3
3 5
1 1 1 1 1
1 1 1 1 1
1 2 3 4 5
2
1 1 1 1 1
1 1 1 1 1
Sample Output
1
2

每个同学 5门科目成绩,给你q个询问,问不严格小于该成绩的同学个数
很容易想到的是用bitset 把小于该成绩的同学全部加进去,最后一个与就行了,可是怎么加进去呢,每次暴力肯定不行 5e4*5e4*5的 时间复杂度直接爆炸,考虑分块,因为已经排好序了,所以找到最后一个小于等于这个成绩的同学在哪一块,那么全部的块全是满足条件的,剩下的暴力加进去就好,可以想到这样的时间复杂度是 最坏情况,5e4*sqrt(5e4)*5的,对于4s,完全足够了

#include <bits/stdc++.h>using namespace std;struct node{    int v,cur;    bool operator <(const node &rhs) const    {        if(v==rhs.v) return cur<rhs.cur;        return v<rhs.v;    }}a[6][50010];bitset<50010> b[6][500];bitset<50010> ans,temp;int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)        {            for(int j=1;j<=5;j++)            {                scanf("%d",&a[j][i].v);                a[j][i].cur=i;            }        }        for(int i=1;i<=5;i++)            sort(a[i]+1,a[i]+n+1);        int sqrn=sqrt(n);        for(int i=1;i<=5;i++)        {            for(int j=1;(j-1)*sqrn<n;j++)            {                int st=(j-1)*sqrn;                b[i][j].reset();                b[i][j]=b[i][j-1];                for(int k=1;st+k<=n&&k<=sqrn;k++)                {                    b[i][j].set(a[i][st+k].cur);                }            }        }        int q;        int pre=0;        scanf("%d",&q);        while(q--){            int d;            ans.reset();            for(int i=1;i<=5;i++)            {                scanf("%d",&d);                d^=pre;                int pos=lower_bound(a[i]+1,a[i]+n+1,(node){d,n+1})-a[i]-1;                int tmp=pos/sqrn;                temp=b[i][tmp];                for(int j=tmp*sqrn+1;a[i][j].v<=d&&j<=n;j++)                    temp.set(a[i][j].cur);                if(i==1)                    ans=temp;                else ans&=temp;            }            int cou=ans.count();            pre=cou;            printf("%d\n",cou );        }    }}
原创粉丝点击