2016_1_17

给5w个5维坐标,5w次询问:给出一个点,求5维都不大于这个点的点数量,强制在线

第一行两个数字n,m,分别代表初始点和询问。
接下去n行,每行5个数代表坐标(坐标小于5w)
接下去m行,每行5个数,真正的询问坐标为当前给的数字异或上一次的答案(第一次就不用异或了)。

每行一个数字对应询问

 

2 2
1 1 1 1 1
2 2 2 2 2
1 1 1 1 1
3 3 3 3 3

1
2

20%数据 n<=100
100%数据 n<=5w

 

之前没有看bitsat ,这道题血崩只有二十分。做法是按每一维排序,然后预处理出每一维每块内有哪些点,就用bitsat来处理了,取个前缀。然后关于每一个询问,每一维查询有哪些是合法的,然后每一维取and,最后count就是答案了。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cstring>
 6 #include <cmath>
 7 #include <bitset>
 8 using namespace std;
 9 const int N = 60003;
10 const int INF = 0x7fffffff;
11 bitset<N>kuai[5][243];
12 bitset<N>ans,linshi;
13 int n,m;
14 struct hp {
15     int x,key;
16     bool operator < (const hp& p) const {
17         return x<p.x;
18     }
19 }a[5][N];
20 int b[5],last,size;
21 int main() {
22     scanf("%d%d",&n,&m);
23     for(int i = 1 ; i <= n ; ++i)
24         for(int j = 0 ; j < 5 ; ++j) 
25             scanf("%d",&a[j][i].x),a[j][i].key = i;
26     for(int j = 0 ; j < 5 ; ++j) sort(a[j]+1,a[j]+1+n);
27     size = sqrt(n);
28     for(int j = 0 ; j < 5 ; ++j) {
29         last = 1;
30         for(int i = 1 ; i <= n ; ++i) {
31             int k = i/size;
32             if(i%size!=0) k++;
33             if(last!=k) kuai[j][k] = kuai[j][k-1],last = k;
34             kuai[j][k].set(a[j][i].key);
35         }
36     }
37     last = 0;
38     for(int i = 1 ; i <= m ; ++i) {
39         for(int j = 0 ; j < 5 ; ++j) scanf("%d",&b[j]),b[j]^=last;
40         for(int j = 0 ; j < 5 ; ++j) {
41             int x = b[j];
42             int l = 1,r = n,maxn = 0;
43             do {
44                 int mid = (l+r)>>1;
45                 if(a[j][mid].x <= x) l = mid + 1,maxn = max(maxn,mid);
46                 else r = mid;
47             }while(l<r);
48             if(a[j][r].x <= x) maxn = max(maxn,r);
49             if(a[j][l].x <= x) maxn = max(maxn,l);
50             while(a[j][maxn+1].x <= x && maxn < n) maxn++;
51             maxn = min(maxn,n);
52             if(maxn==0) {
53                 ans.reset();
54                 break;
55             }
56             int RP = maxn/size;
57             if(j==0) ans = kuai[j][RP];
58             else linshi = kuai[j][RP];
59             for(int kk = maxn/size*size+1 ; kk <= maxn ; ++kk) {
60                 if(j==0) ans.set(a[j][kk].key);
61                 else linshi.set(a[j][kk].key);
62             }
63             if(j!=0)ans &= linshi;
64         }
65         last = ans.count();
66         printf("%d\n",last);
67     }
68 }
View Code

 

转载于:https://www.cnblogs.com/registerzxr/p/5137738.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值