转载自here
分块的原因是因为空间复杂度太高,不然的话可以直接开bitset<50000> b[5][50000]
题意:
给5w个5维坐标,5w次询问:给出一个点,求5维都不大于这个点的点数量,强制在线
思路:
首先,如果维数低的话,就直接裸着跑kdtree就好了。
但是这个有五维,所以 k−dtree 就不要想了
我写的是分块+ bitset
我预处理 5⋅n−−√ 个 bitset , bitset[i][j] 表示在第i维,当前排名为 j⋅n−−√ 的时候的 bitset 的样子
那么每次询问的时候,我们就可以从最近的 bitset 里面转移过来就好了
对于每一个case,预处理的复杂度是 O(n) 的,询问的复杂度是 5⋅n−−√ ,所以跑过去了~
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <bitset>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 1006
#define mod 1000000007
#define eps 1e-9
#define PI acos(-1)
const double EP = 1E-10 ;
int Num;
//const int inf=0x7fffffff;
const ll inf=999999999;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
//*************************************************************************************
bitset<50001> b[7][270];
bitset<50001> Ans[7];
int now[7];
struct node
{
int x,y;
};
bool cmp(node a,node b)
{
return a.x<b.x;
}
node a[7][50001];
int l[300],r[300];
int belong[50001];
int main()
{
int t;scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
int n=read(),m=read();
for(int i=1;i<=5;i++)
for(int j=1;j<250;j++)
b[i][j].reset();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=5;j++)
{
a[j][i].x=read();
a[j][i].y=i;
}
}
for(int i=1;i<=5;i++)
sort(a[i]+1,a[i]+n+1,cmp);
int block = sqrt(n);
int num = n/block;
if(n%block)num++;
for(int i=1;i<=num;i++)
l[i]=(i-1)*block+1,r[i]=i*block;
r[num]=n;
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
for(int i=1;i<=5;i++)
{
for(int j=1;j<=num;j++)
{
b[i][j]|=b[i][j-1];
for(int k=l[j];k<=r[j];k++)
b[i][j][a[i][k].y]=1;
}
}
int q=read();
int lastans = 0;
while(q--)
{
for(int i=1;i<=5;i++)
now[i]=read();
for(int i=1;i<=5;i++)
now[i]^=lastans;
for(int i=1;i<=5;i++)
Ans[i].reset();
for(int i=1;i<=5;i++)
{
int L = 0,R = n;
while(L<=R)
{
int mid = (L+R)/2;
if(now[i]>=a[i][mid].x)
L = mid+1;
else
R = mid-1;
}
int p = L-1;
if(p==0)continue;
Ans[i]|=b[i][belong[p]-1];
for(int j=l[belong[p]];j<=p;j++)
Ans[i][a[i][j].y]=1;
}
Ans[1] = Ans[1]&Ans[2]&Ans[3]&Ans[4]&Ans[5];
lastans = Ans[1].count();
printf("%d\n",lastans);
}
}
}