卧薪尝胆,厚积薄发。
Scores
Date: Fri Jul 13 20:23:47 CST 2018 In Category: NoCategory

Description:

五维偏序。
$1\le N \le50000$

Solution:

看到 $50000$ 的数据范围大概算法就是 $O(\sqrt N)$ 的。
可以将每一维排序,记录一个前缀 $bitset$ 表示哪个出现过,这样对于一个查询只要找到每一维对应的位置再与起来就好,但是空间开不下,于是考虑每 $\sqrt n$ 个数分一个块,维护整块的前缀和,这样只要找到对应的块再加上块内零散的最后再与起来就好。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<bitset>
#include<cstring>
using namespace std;
int n,m,q;
#define MAXN 50010
#define MAXB 300
struct node
{
int v,id,belong;
}a[6][MAXN];
int type;
int L[MAXB],R[MAXB],tot;
void build(int l,int r,int k)
{
L[k] = l;R[k] = r;
return;
}
bitset<MAXN> b[6][MAXB];
bool cmp(node a,node b){return a.v < b.v;}
void work()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= 5;++j)
{
scanf("%d",&a[j][i].v);
a[j][i].id = i;
}
}
tot = sqrt(n);
for(int i = 1;i <= tot;++i)
build((i - 1) * tot + 1,i * tot,i);
if(tot * tot < n){build(R[tot] + 1,n,tot + 1);++tot;}
bitset<MAXN> s;
for(type = 1;type <= 5;++type)
{
sort(a[type] + 1,a[type] + 1 + n,cmp);
s.reset();
for(int i = 1;i <= tot;++i)
{
for(int j = L[i];j <= R[i];++j)
{
s[a[type][j].id] = 1;
a[type][j].belong = i;
}
b[type][i] = s;
}
}
scanf("%d",&q);
bitset<MAXN> ans;
int lastans = 0;
for(int i = 1;i <= q;++i)
{
ans.set();
s.reset();
for(type = 1;type <= 5;++type)
{
int k;
scanf("%d",&k);k ^= lastans;
int p;
for(p = 1;a[type][L[p + 1]].v <= k && p + 1 <= tot;++p);
s = b[type][p - 1];
for(int j = L[p];j <= R[p];++j)
{
if(a[type][j].v > k)continue;
s[a[type][j].id] = 1;
}
ans = ans & s;
}
printf("%d\n",lastans = ans.count());
}
return;
}
int main()
{
int testcases;
scanf("%d",&testcases);
for(int i = 1;i <= testcases;++i)
work();
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡