ACM-ICPC国际大学生程序设计竞赛北京赛区(2015)网络赛 Scores
#1236 : Scores
描述
Kyle is a student of Programming Monkey Elementary School. Just as others, he is deeply concerned with his grades.
Last month, the school held an examination including five subjects, without any doubt, Kyle got a perfect score in every single subject.
There are n students took part in this examination(not including Kyle), and everyone got an integer between 1 to m as the score of one subject.
Now, looking at the grade table of these n students, Kyle wants to know how many students still did no better than him even if his scores are something else – Here, “no better” means there is no subject in which the student got strictly greater score than Kyle.
输入
There are multiple test cases.
The first line of the input contains an integer T (T <= 3) which means the number of test cases.
The first line of each test case contains two integers, n, m(n, m≤ 50,000), which are the number of students and the perfect score of each subject.
In the next n lines, each line consists of five integers, indicating a student’s scores.
Then one line follows. This line contains an integer q(q≤ 50,000) indicating the number of queries.
In the next q lines, each line contains five integers as well, representing a query. Each query indicates a set of scores, and for each query, you should figure out that if Kyle's grade is this set of scores, how many students still did no better than him. But for the sake of security, only the first query is in its original form, and other queries are encrypted. To decrypt a query, you must let each integer in the query do xor operation with the answer of last query. It's guaranteed that all the decrypted queries contain integers between 1 and 50000.
输出
For each test case, you should output q lines as the answer for all queries.
提示
In case 1, there are two students with different scores and the scores of the first student (1, 1, 1, 1, 1) are not larger than the first query (1 1 1 1 1) in every subject, so the answer for this query is 1.
After having xor operation with the last answer 1, the second query (3,3,3,3,3) will be decrypted into (2, 2, 2, 2, 2). Because both students’ scores are no better than (2, 2, 2, 2, 2), so the answer for query 2 is 2.
- 样例输入
-
2 2 3 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 3 3 3 3 3 3 5 1 1 1 1 1 1 1 1 1 1 1 2 3 4 5 2 1 1 1 1 1 1 1 1 1 1
- 样例输出
-
1 2 2 2
分析:在线求五维偏序点对数;
考虑bitset存编号,预处理前缀bitset并且分块;
对于每次询问,每一维可以直接二分得到位置,把当前bitset和剩下的或起来就是当前这一维的;
最后把五维或起来求count即可;
代码:#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define inf 0x3f3f3f3f #define mod 998244353 #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls (rt<<1) #define rs (rt<<1|1) #define all(x) x.begin(),x.end() const int maxn=5e4+10; const int N=4e5+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;} int n,m,k,t,bl[maxn]; struct node { int id,v; bool operator<(const node&p)const { return v<p.v; } }a[5][maxn]; bitset<maxn>dp[5][230],ans[5]; int main(){ int i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); rep(i,0,4)rep(j,1,229)dp[i][j].reset(); rep(i,1,n)rep(j,0,4) { scanf("%d",&k); a[j][i]=node{i,k}; } rep(i,0,4)sort(a[i]+1,a[i]+n+1); int sz=(int)round(sqrt(n)); rep(i,1,n)bl[i]=(i-1)/sz+1; rep(i,0,4) { int pos=0,go=0; while(++go<=n) { pos++; dp[i][pos]|=dp[i][pos-1]; dp[i][pos][a[i][go].id]=1; while(go+1<=n&&bl[go+1]==bl[go]) { dp[i][pos][a[i][++go].id]=1; } } } int q,lst=0; scanf("%d",&q); while(q--) { int qu[5]; rep(i,0,4) { ans[i].reset(); scanf("%d",&qu[i]); qu[i]^=lst; int l=1,r=n,ret=0; while(l<=r) { int mid=l+r>>1; if(qu[i]>=a[i][mid].v)ret=mid,l=mid+1; else r=mid-1; } if(!ret)continue; else { ans[i]|=dp[i][bl[ret]-1]; for(j=(bl[ret]-1)*sz+1;j<=ret;j++)ans[i][a[i][j].id]=1; } } lst=(ans[0]&ans[1]&ans[2]&ans[3]&ans[4]).count(); printf("%d\n",lst); } } return 0; }