[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个预处理的结果+最多√N次暴力单bit插入就能得到S(i)。然后就是and和count了。
#include <bits/stdc++.h> using namespace std; #ifndef ONLINE_JUDGE #include "local.h" #endif #define X first #define Y second #define pb(x) push_back(x) #define mp(x, y) make_pair(x, y) #define all(a) (a).begin(), (a).end() #define mset(a, x) memset(a, x, sizeof(a)) #define mcpy(a, b) memcpy(a, b, sizeof(a)) typedef long long ll; template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);} template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} int k; struct Node { int a[5]; int id; void read() { for (int i = 0; i < 5; i ++) { scanf("%d", a + i); } } bool operator < (const Node &that) const { return a[k] < that.a[k]; } }; Node stu[1 << 16]; int r[5][1 << 16], id[5][1 << 16]; bitset<1 << 16> bs[5][1 << 8]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); #endif // ONLINE_JUDGE int T, n, q, m; cin >> T; while (T --) { cin >> n >> m; for (int i = 0; i < n; i ++) { stu[i].read(); stu[i].id = i; } int L = sqrt(n + 0.5); for (int i = 0; i < 5; i ++) { k = i; sort(stu, stu + n); bitset<1 << 16> bbs; for (int j = 0; j < n; j ++) { r[i][j] = stu[j].a[i]; id[i][j] = stu[j].id; bbs[stu[j].id] = 1; if (j % L == L - 1 || j == n - 1) { bs[i][j / L] = bbs; } } } int lastans = 0; cin >> q; while (q --) { Node qry; qry.read(); bitset<1 << 16> ans; for (int i = 0; i < 5; i ++) { qry.a[i] ^= lastans; bitset<1 << 16> buf; int pos = upper_bound(r[i], r[i] + n, qry.a[i]) - r[i]; if (pos / L) buf = bs[i][pos / L - 1]; while (pos % L) buf[id[i][-- pos]] = 1; if (i) ans &= buf; else ans = buf; } printf("%d\n", lastans = ans.count()); } } return 0; }