HihoCoder1236 Scores
Scores
求五维偏序(≤)。强制在线。
n,q≤50000
烂大街的题解
考虑如果我们能用bitset找到每一维有哪些比询问点小,然后把每一维的结果取交集,得到的就是答案了。
然后对每一维分块处理前缀,询问时二分得到排名,将前面整块的和末尾的合并一下就行了。
时间复杂度O(nq32)。分块对时间复杂度几乎没什么影响,重要的是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; }
静渊以有谋,疏通而知事。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步