HihoCoder 1236 Scores - bitset - 分块

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
2
2

Hint

In case 1, there are two students with different scores and the scores of the first student (1, 1, 1, 1, 1) are not larger than the first query (1 1 1 1 1) in every subject, so the answer for this query is 1.

After having xor operation with the last answer 1, the second query (3,3,3,3,3) will be decrypted into (2, 2, 2, 2, 2). Because both students’ scores are no better than  (2, 2, 2, 2, 2), so the answer for query 2 is 2.



  题目大意 给定n个五元组,在给定q个五元组,询问每个5元组在偏序意义下,有多少个小于等于它。(强制在线,多组数据)

  五维偏序,根据常用套路n - 1维套树,总时间复杂度O(nlog4n)。请问这和暴力区别有多大?

  既然无法区分套树做法和暴力。那就暴力 + 黑科技卡过去吧。

  如果你认为这个暴力是每个询问直接去for套for(第二个for是比较),总时间复杂度为O(nqk)的暴力,那你没救了,赶快换道题吧。

  考虑如果每一维单独比较,然后最后把所有可行的集合取交集,这样似乎可以继续进行优化。

  每一维比较的时候可以用二分查找。既然又要取交集,那就bitset顶上吧。然而你需要对每一维排序后进行,bitset求前缀并(下标),这样你就可以顺利O(1)求出在这一维可行的集合。

  看起来查询很顺利,但是预处理不是怎么想的,首先5 * 4 * 50000 * 50000 / 32空间直接炸掉了。另外bitset赋值也不是O(1),所以时间也炸掉了。

  因此得均衡一下查询和预处理的耗时。所以想到了根号分块。

  然后随便搞就行了。总时间复杂度为(其中k为维度,这里为5)

  然后表示开始手抽每次询问给ans赋值时,一位一位地设成1,然后成功三发TLE,并且十分懵逼。

Code

  1 /**
  2  * HihoCoder
  3  * Problem#1236
  4  * Accepted
  5  * Time: 1696ms
  6  * Memory: 22528k
  7  */
  8 #include <bits/stdc++.h>
  9 using namespace std;
 10 typedef bool boolean;
 11
 12 int opt;
 13 typedef class Data {
 14     public:
 15         int w[6];
 16
 17         friend boolean operator < (const Data& a, const Data& b) {
 18             return a.w[opt] < b.w[opt];
 19         }
 20 }Data;
 21
 22 int n, m, q;
 23 int cs, cc;
 24 Data ds[50005];
 25 boolean endflag[50005];
 26 int order[6][50005];
 27 bitset<50001> bs[6][400];
 28
 29 inline void init() {
 30     scanf("%d%d", &n, &m);
 31     cs = sqrt(n + 0.5);
 32     cc = (n + cs - 1) / cs;
 33 //    printf("Chunks datas: %d %d\n", cs, cc);
 34     for(int i = 0; i < n; i++) {
 35         ds[i].w[0] = i;
 36         endflag[i] = !((i + 1) % cs);
 37 //        if(endflag[i])    printf("endflag:%d\n", i);
 38         for(int j = 1; j <= 5; j++)
 39             scanf("%d", ds[i].w + j);
 40     }
 41     endflag[n - 1] = true;
 42 }
 43
 44 inline void init_chunks(int k) {
 45     opt = k;
 46     sort(ds, ds + n);
 47     for(int i = 0; i < n; i++)
 48         order[k][i] = ds[i].w[0];
 49     bitset<50001> b;
 50     for(int j = 0; j < n; j++) {
 51         b[order[k][j]] = 1;
 52         if(endflag[j])    bs[k][j / cs] = bitset<50001>(b);
 53     }
 54 }
 55
 56
 57 inline void init_chunks() {
 58     for(int i = 1; i <= 5; i++)
 59         init_chunks(i);
 60     opt = 0;
 61     sort(ds, ds + n);
 62 }
 63
 64 //int bitsetc = 0, cnt = 0;
 65
 66 inline bitset<50001> solve(int k, int val) {
 67     int l = 0, r = n - 1, ri;
 68     bitset<50001> rt;
 69     while(l <= r) {
 70 //        cnt++;
 71         int mid = (l + r) >> 1;
 72         if(ds[order[k][mid]].w[k] > val)    r = mid - 1;
 73         else l = mid + 1;
 74     }
 75     if(r >= cs)
 76         rt = bitset<50001>(bs[k][r / cs - 1]);//, bitsetc++;
 77     ri = r / cs * cs;
 78     for(; ri <= r; ri++)
 79         rt[order[k][ri]] = 1;//, cnt++;
 80     return rt;
 81 }
 82
 83 inline void solve() {
 84     int lastans = 0;
 85     scanf("%d", &q);
 86     bitset<50001> buf;
 87     for(int i = 0; i < n; i++)
 88         buf[i] = 1;
 89     while(q--) {
 90         bitset<50001> ans(buf);
 91         for(int i = 1, x; i <= 5; i++) {
 92             scanf("%d", &x);
 93             x ^= lastans;
 94 //            bitsetc++;
 95             ans &= solve(i, x);
 96         }
 97         lastans = ans.count();
 98 //        bitsetc++;
 99         printf("%d\n", lastans);
100 //        fprintf(stderr, "Used:%d for uses:%d bitset uses:%d \n", bitsetc * 50001 / 32 + cnt, cnt, bitsetc);
101     }
102 }
103
104 int T;
105 int main() {
106     scanf("%d", &T);
107     while(T--) {
108         init();
109         init_chunks();
110         solve();
111     }
112 //    fprintf(stderr, "Time:%dms\n", clock());
113     return 0;
114 }
时间: 2024-10-09 22:12:26

HihoCoder 1236 Scores - bitset - 分块的相关文章

hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题

题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给定的学生成绩都异或上一次的答案 先将学生按每一门成绩都排一次序 这里将学生分块成sqrt(n)的块数,然后在当前块中用bitset容器来记录含有学生的状态 这里可以记录状态的前缀和,因为比后面成绩好的,必然比前面的学生的成绩也好 查询的时候只要查到正好比他高的学生属于哪一块,这样只要访问sqrt(n

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

北京网络赛的题- -.当时没思路,听大神们说是分块+bitset,想了一下发现确实可做,就试了一下,T了好多次终于过了 题意: 初始有n个人,每个人有五种能力值,现在有q个查询,每次查询给五个数代表查询的五种能力值,输出有多少个人每种能力值都比查询的小 n和q都是50000,每种能力值最大也为50000 思路: 对于某一个大小的能力值,有哪些人的此项能力值比他小可以用一个50000的bitset表示.这样我们在查询的时候就可以拿到5个对应的bitset,对其进行and就可以得出最终的人数 这样每

Hiho coder 1236 2015 北京网络赛 Score

五维偏序..一开始被吓到了,后来知道了一种BITSET分块的方法,感觉非常不错. 呆马: 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <vector> 7 #include <bitset> 8 #define inf 100000000

[hihoCoder1236 Scores 2015BeijingOnline]简单粗暴的分块+简单粗暴的bitset

题意:50000个5维向量,50000次询问每一维都不大于某一向量的向量个数,强制在线. 思路:做完这题才知道bitset效率这么高,自己本地测试了下1s可以操作1010个bit,orz简单粗暴 令S(i)表示第i维比当前向量的i维小的向量集,则答案为count(∩S(i)),0≤i‹5 每个向量都可以和一个id绑定(取下标就行了),绑定后就可以考虑bitset了.分别按每一维排序,每隔√N个位置预处理下当前位置之前的id的bitset 查询时,对每一维二分得到最大位置,然后用1个预处理的结果+

【分块】【bitset】hdu6085 Rikka with Candies

给你数组A和B,A B中的元素大小都不超过5w,且两两不同. q次询问,每次给你个k,问你有多少对(i,j),满足A(i)%B(j)==k. 如题目所言模拟bitset的过程,实质上是个分块,每块的大小定为63. 一个小技巧是对于最终的那个数组w,分块后记63个w数组,每个数组最前面一块是零散的部分,大小从1~63,这样比较好操作. 最后把63个w里面的每一位的值都异或起来,就是对应的k的答案. #include<cstdio> #include<cstring> #include

hihocoder#1513 : 小Hi的烦恼 bitset

目录 题目链接 题解 代码 题目链接 hihocoder#1513 : 小Hi的烦恼 题解 cdq 套cdq 套cdq 套cdq就完了呀 对每一科开n个bitset 表示该科目前i个有谁 每次查询都&起来就好了 代码 #include<cstdio> #include<bitset> #include<cstring> #include<algorithm> #define LL long long #define gc getchar() #def

hihocoder 1513 小Hi的烦恼——bitset

题目:http://hihocoder.com/problemset/problem/1513 自带的题解写得很好-- #include<cstdio> #include<cstring> #include<algorithm> #include<bitset> using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0')

Bzoj 2453: 维护队列 &amp;&amp; Bzoj 2120: 数颜色 分块,bitset

2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 578  Solved: 247[Submit][Status][Discuss] Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你

HihoCoder - 1513 bitset处理五维偏序

题意:给出\(n<3e4\)个有序组\((a,b,c,d,e)\),求对第\(i\)个有序组有多少个\(j\)满足\((a_j<a_i,b_j<b_i,c_j<c_i,d_j<d_i,e_j<e_i)\) 五维偏序问题按套路来可以排序+树套树套树套树(打死 然而这是显然连\(O(n^2)\)暴力都不如的 可是题目给4s,\(O(n^2)\)是不可能的,但在神奇的bitset加持下\(O(5*n^2/32)\)的时空复杂度是可以卡过去的! 用bitset表示集合,\(bi