HihoCoder1236 Scores

Scores

求五维偏序(≤)。强制在线。

\(n,q\le 50000\)

烂大街的题解

考虑如果我们能用bitset找到每一维有哪些比询问点小,然后把每一维的结果取交集,得到的就是答案了。

然后对每一维分块处理前缀,询问时二分得到排名,将前面整块的和末尾的合并一下就行了。

时间复杂度\(O(\frac{nq}{32})\)。分块对时间复杂度几乎没什么影响,重要的是bitset的操作。

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
	T x=0,w=1;char c=getchar();
	for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*w;
}
template<class T>il T read(T&x){
	return x=read<T>();
}
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

co int N=50000+1,M=250;
int n,m,q,L[M],R[M],B[N];
pii scores[5][N];
bitset<N> S[5][M],A[5];

void solve(int u,int x){
	int t=lower_bound(scores[u],scores[u]+n,pii(x,n))-scores[u];
	A[u]=S[u][B[t]-1];
	for(int i=L[B[t]];i<t;++i) A[u][scores[u][i].second]=1;
}
void real_main(){
	read(n),read(m);
	for(int i=0;i<n;++i)
		for(int j=0;j<5;++j) read(scores[j][i].first),scores[j][i].second=i;
	int len=sqrt(n),block=n/len+(n%len?1:0);
	L[0]=R[0]=-1;
	for(int i=1;i<=block;++i) L[i]=(i-1)*len,R[i]=i*len;
	R[block]=n;
	for(int i=0;i<5;++i){
		sort(scores[i],scores[i]+n);
		S[i][0]=0;
		for(int j=1;j<=block;++j){
			S[i][j]=S[i][j-1];
			for(int k=L[j];k<R[j];++k) S[i][j][scores[i][k].second]=1;
		}
	}
	for(int i=1;i<=block;++i)
		for(int j=L[i];j<R[i];++j) B[j]=i;
	read(q);
	int ans=0;
	while(q--){
		for(int i=0;i<5;++i) solve(i,read<int>()^ans);
		for(int i=4;i;--i) A[i-1]&=A[i];
		ans=A[0].count();
		printf("%d\n",ans);
	}
}
int main(){
	for(int t=read<int>();t--;) real_main();
	return 0;
}

posted on 2019-08-07 15:03  autoint  阅读(111)  评论(0编辑  收藏  举报

导航