2015北京网络赛 J Scores bitset+分块
题意:50000组5维数据,50000个询问,问有多少组每一维都不大于询问的数据
思路:赛时没有思路,后来看解题报告也因为智商太低看了半天看不懂。bitset之前没用过,查了下发现其实就是一个二进制表示,这里的每一位就表示原序中的状态。
建一个bitset<50000> bs[6][sqrt(50000)], bs[i][j] 就表示在第i维上前j个块中的数据在原序中是哪些位置。
1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <cstring> 11 #include <map> 12 #include <stack> 13 #include <set> 14 #include <bitset> 15 #define LL long long 16 #define eps 1e-8 17 #define INF 0x3f3f3f3f 18 #define MAXN 50005 19 using namespace std; 20 struct Node{ 21 int x, pos; 22 }; 23 bitset<MAXN> bs[6][230]; 24 int t[6]; 25 bitset<MAXN> res[6], w; 26 bool compare(Node a, Node b){ 27 return a.x < b.x; 28 } 29 Node s[6][MAXN]; 30 int main() 31 { 32 #ifndef ONLINE_JUDGE 33 freopen("in.txt", "r", stdin); 34 //freopen("out.txt", "w", stdout); 35 #endif // OPEN_FILE 36 int T; 37 int n, m; 38 scanf("%d", &T); 39 while (T--){ 40 scanf("%d%d", &n, &m); 41 for (int i = 1; i <= n; i++){ 42 for (int j = 1; j <= 5; j++){ 43 scanf("%d", &s[j][i].x); 44 s[j][i].pos = i; 45 } 46 } 47 for (int i = 1; i <= 5; i++){ 48 sort(s[i] + 1, s[i] + 1 + n, compare); 49 } 50 int u = sqrt(n); 51 int num = n / u; 52 if (n % u != 0){ 53 num++; 54 } 55 memset(bs, 0, sizeof(bs)); 56 for (int i = 1; i <= 5; i++){ 57 for (int j = 1;j <= num; j++){ 58 bs[i][j] |= bs[i][j - 1]; 59 int left = (j - 1) * u + 1, right = j * u; 60 if (right > n){ 61 right = n; 62 } 63 for (int k = left; k <= right; k++){ 64 bs[i][j][s[i][k].pos] = 1; 65 } 66 } 67 } 68 int ans = 0; 69 int q; 70 scanf("%d", &q); 71 while (q--){ 72 for (int i = 1; i <= 5; i++){ 73 scanf("%d", &t[i]); 74 t[i] ^= ans; 75 } 76 for (int i = 1; i <= 5; i++){ 77 int left = 1, right = n; 78 while (left < right){ 79 int mid = (left + right) >> 1; 80 if (s[i][mid].x > t[i]){ 81 right = mid; 82 } 83 else{ 84 left = mid + 1; 85 } 86 } 87 int pos; 88 if (s[i][left].x > t[i]){ 89 pos = left - 1; 90 } 91 else{ 92 pos = left; 93 } 94 int u_pos = (pos - 1) / u; 95 res[i] = bs[i][u_pos]; 96 for (int j = u_pos * u + 1; j <= pos; j++){ 97 res[i][s[i][j].pos] = 1; 98 } 99 } 100 w = res[1]; 101 for (int i = 2; i <= 5; i++){ 102 w &= res[i]; 103 } 104 ans = w.count(); 105 printf("%d\n", ans); 106 } 107 } 108 }