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
/**
* HihoCoder
* Problem#1236
* Accepted
* Time: 1696ms
* Memory: 22528k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; int opt;
typedef class Data {
public:
int w[]; friend boolean operator < (const Data& a, const Data& b) {
return a.w[opt] < b.w[opt];
}
}Data; int n, m, q;
int cs, cc;
Data ds[];
boolean endflag[];
int order[][];
bitset<> bs[][]; inline void init() {
scanf("%d%d", &n, &m);
cs = sqrt(n + 0.5);
cc = (n + cs - ) / cs;
// printf("Chunks datas: %d %d\n", cs, cc);
for(int i = ; i < n; i++) {
ds[i].w[] = i;
endflag[i] = !((i + ) % cs);
// if(endflag[i]) printf("endflag:%d\n", i);
for(int j = ; j <= ; j++)
scanf("%d", ds[i].w + j);
}
endflag[n - ] = true;
} inline void init_chunks(int k) {
opt = k;
sort(ds, ds + n);
for(int i = ; i < n; i++)
order[k][i] = ds[i].w[];
bitset<> b;
for(int j = ; j < n; j++) {
b[order[k][j]] = ;
if(endflag[j]) bs[k][j / cs] = bitset<>(b);
}
} inline void init_chunks() {
for(int i = ; i <= ; i++)
init_chunks(i);
opt = ;
sort(ds, ds + n);
} //int bitsetc = 0, cnt = 0; inline bitset<> solve(int k, int val) {
int l = , r = n - , ri;
bitset<> rt;
while(l <= r) {
// cnt++;
int mid = (l + r) >> ;
if(ds[order[k][mid]].w[k] > val) r = mid - ;
else l = mid + ;
}
if(r >= cs)
rt = bitset<>(bs[k][r / cs - ]);//, bitsetc++;
ri = r / cs * cs;
for(; ri <= r; ri++)
rt[order[k][ri]] = ;//, cnt++;
return rt;
} inline void solve() {
int lastans = ;
scanf("%d", &q);
bitset<> buf;
for(int i = ; i < n; i++)
buf[i] = ;
while(q--) {
bitset<> ans(buf);
for(int i = , x; i <= ; i++) {
scanf("%d", &x);
x ^= lastans;
// bitsetc++;
ans &= solve(i, x);
}
lastans = ans.count();
// bitsetc++;
printf("%d\n", lastans);
// fprintf(stderr, "Used:%d for uses:%d bitset uses:%d \n", bitsetc * 50001 / 32 + cnt, cnt, bitsetc);
}
} int T;
int main() {
scanf("%d", &T);
while(T--) {
init();
init_chunks();
solve();
}
// fprintf(stderr, "Time:%dms\n", clock());
return ;
}
HihoCoder 1236 Scores - bitset - 分块的更多相关文章
- hihocoder #1236 Scores (15北京赛区网络赛J) (五维偏序,强制在线,bitset+分块)
链接:http://hihocoder.com/problemset/problem/1236 思路; 有n个五维的向量,给出q个询问,每个询问是一个五维向量,问有多少个向量没有一维比这个向量大.并且 ...
- HihoCoder - 1236 Scores (五维偏序,分块+bitset)
题目链接 题意:给定n个五维空间上的点,以及m组询问,每组询问给出一个点,求五个维度都不大于它的点有多少个,强制在线. 神仙题 单独考虑每个维度,把所有点按这个维度上的大小排序,然后分成T块,每块用一 ...
- hihocoder1236(2015长春网赛J题) Scores(bitset && 分块)
题意:给你50000个五维点(a1,a2,a3,a4,a5),50000个询问(q1,q2,q3,q4,q5),问已知点里有多少个点(x1,x2,x3,x4,x5)满足(xi<=qi,i=1,2 ...
- 2015北京网络赛 J Scores bitset+分块
2015北京网络赛 J Scores 题意:50000组5维数据,50000个询问,问有多少组每一维都不大于询问的数据 思路:赛时没有思路,后来看解题报告也因为智商太低看了半天看不懂.bitset之前 ...
- hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题
题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给 ...
- HihoCoder#1513 : 小Hi的烦恼(五维数点 bitset 分块)
题意 题目链接 Sol 五位数点问题,写个cdq分治套cdq分治套cdq分治套cdq分析就完了 可以用bitset搞 对于每一科开\(n\)个bitset,其中\(b[i]\)表示的排名为\(1 - ...
- 【卡常 bitset 分块】loj#6499. 「雅礼集训 2018 Day2」颜色
好不容易算着块大小,裸的分块才能过随机极限数据:然而这题在线的数据都竟然是构造的…… 题目描述 有 $n$ 个数字,第 $i$ 个数字为 $a_i$. 有 $m$ 次询问,每次给出 $k_i$ 个区间 ...
- LOJ bitset+分块 大内存毒瘤题
题面 $ solution: $ 真的没有想到可以用分块. 但是可以发现一个性质,每个询问只关心这个点最后一次赋值操作,和这个赋值操作后的所有取 $ min $ 操作.这个感觉很有用,但是真的很难让人 ...
- 洛谷 P5332 - [JSOI2019]精准预测(2-SAT+bitset+分块处理)
洛谷题面传送门 七月份(7.31)做的题了,题解到现在才补,不愧是 tzc 首先不难发现题目中涉及的变量都是布尔型变量,因此可以考虑 2-SAT,具体来说,我们将每个人在每个时刻的可能的状态表示出来. ...
随机推荐
- cocos2dx C++为Sprite添加触摸事件监听器
1.首先头文件定义事件处理的函数原型 private: bool onTouchBegan(Touch* tTouch,Event* eEvent);//手指按下事件 void onTouchMove ...
- 【网络设备】某防火墙基于IP地址的目的地址转换
由于来自Internet的对政府,企业的网络攻击日益频繁,因此需要对内网中向外网提供访问服务的关键设备进行有效保护.采用目的地址NAT可以有效地将内部网络地址对外隐藏. 图中:公网中Internet用 ...
- RSA加解密 公钥加密私钥解密 公加私解 && C++ 调用openssl库 的代码实例
前提:秘钥长度=1024 ============================================== 对一片(117字节)明文加密 ========================= ...
- Python学习笔记之装饰器原理
def decorator(fn): def wrapper(): print("询价") fn() print("购买成功!") return wrapper ...
- jdk8新特性-亮瞎眼的lambda表达式
jdk8之前,尤其是在写GUI程序的事件监听的时候,各种的匿名内部类,大把大把拖沓的代码,程序毫无美感可言!既然Java中一切皆为对象,那么,就类似于某些动态语言一样,函数也可以当成是对象啊!代码块也 ...
- GE与POST方法区别
1.用途. GET方法一般用于查询并获取信息,这意味着它是幂等的(对同一个url的多个请求,返回结果完全一样),因为没有修改资源状态,所以它是安全的.而POST一般用于更新资源信息,既不是幂等,也不是 ...
- linux工作目录切换命令
1.pwd命令 pwd命令用于显示用户当前所处的工作目录,格式为“pwd [选项]”. 2.cd命令 cd命令用于切换工作路径,格式为“cd [目录名称]”. 这个命令应该是最常用的一个Linux命令 ...
- Yii2 Gridview查询关联筛选
- C++前置声明
[1]一般的前置函数声明 见过最多的前置函数声明,基本格式代码如下: #include <iostream> using namespace std; void fun(char ch, ...
- 仿照admin实现一个自定义的增删改查的组件
1.首先,创建三个项目,app01,app02,stark,在settings里边记得配置.然后举例:在app01的model里边写表,用的db.sqlite3,所以数据库不用再settings里边配 ...