1 /* 2 题意:五维偏序,n<=50000,有n个五元组,Q个询问,对于每个询问五元组,查询有多少个小于等于该询问的五元组 3 题解:分块,对于每一维,利用bitset维护一个分块,表示在当前位置之前,小于等于当前位置的状态,不同分块状态之间的转移应包括原有的状态,加上当前分块的情况 4 对于每个询问,二分小于每一维的位置,前缀部分可用分块的信息,然后暴力剩下的部分。最终的结果是五个维之间的与。 5 时间:2018.07.19 6 */ 7 8 #include <bits/stdc++.h> 9 using namespace std; 10 11 typedef long long LL; 12 const int MAXN = 50005; 13 const LL MOD7 = 1e9+7; 14 15 inline int read() 16 { 17 int x=0,f=1;char c=getchar(); 18 while (c<'0' || c>'9') {c=='-' && (f=-1);c=getchar();} 19 while (c>='0' && c<='9') {x=x*10+c-'0',c=getchar();} 20 return x*f; 21 } 22 23 struct Node 24 { 25 int x,y; 26 }a[7][50005]; 27 28 int cmp(Node ca,Node cb) 29 { 30 return ca.x<cb.x; 31 } 32 33 int belong[MAXN],l[MAXN],r[MAXN],qsize,num; 34 bitset<50005> b[7][500]; 35 bitset<50005> Ans[7]; 36 int n,Q,m; 37 38 void build() 39 { 40 qsize = sqrt(n); 41 num = qsize; 42 if (num*num<n) ++num; 43 for (int i=1;i<num;++i) 44 { 45 l[i]=(i-1)*qsize+1; 46 r[i]=i*qsize; 47 for (int j=l[i];j<=r[i];++j) belong[j]=i; 48 } 49 l[num]=(num-1)*qsize+1; 50 r[num]=n; 51 for (int j=l[num];j<=r[num];++j) belong[j]=num; 52 } 53 54 55 int main() 56 { 57 #ifndef ONLINE_JUDGE 58 freopen("test.txt","r",stdin); 59 #endif // ONLINE_JUDGE 60 int Case; 61 scanf("%d",&Case); 62 while (Case--) 63 { 64 n=read(),m=read(); 65 for (int i=1;i<=n;++i) 66 { 67 for (int j=1;j<=5;++j) 68 { 69 a[j][i].x=read(); 70 a[j][i].y=i; 71 } 72 } 73 build(); 74 for (int i=0;i<=num;++i) 75 { 76 for (int j=1;j<=5;++j) 77 { 78 b[j][i].reset(); 79 } 80 } 81 for (int j=1;j<=5;++j) 82 { 83 sort(a[j]+1,a[j]+1+n,cmp); 84 for (int i=1;i<=num;++i) 85 { 86 b[j][i]|=b[j][i-1]; 87 for (int k=l[i];k<=r[i];++k) 88 b[j][i][a[j][k].y]=1; 89 } 90 } 91 92 Q=read(); 93 int now[7]; 94 int ans=0; 95 for (int i=1;i<=Q;++i) 96 { 97 for (int j=1;j<=5;++j) 98 { 99 now[j]=read(); 100 if (i!=1) now[j]^=ans; 101 Ans[j].reset(); 102 } 103 for (int j=1;j<=5;++j) 104 { 105 // int p = a[j]+1+n - upper_bound(a[j]+1, a[j]+1+n, now[j]); 106 int L=1,R=n; 107 int mid; 108 while (L<=R) 109 { 110 mid =(L+R)/2; 111 // printf("L=%d R=%d mid=%d a[%d][%d].x=%d now[%d]=%d\n", L,R,mid,j,mid,a[j][mid].x,j,now[j]); 112 if (a[j][mid].x<=now[j]) L=mid+1; 113 else R=mid-1; 114 } 115 int p=L-1; 116 // printf("p=%d\n",p); 117 Ans[j] |= b[j][belong[p]-1]; 118 for (int k=l[belong[p]];k<=p;++k) 119 Ans[j][a[j][k].y]=1; 120 } 121 Ans[1]=Ans[1]&Ans[2]&Ans[3]&Ans[4]&Ans[5]; 122 ans = Ans[1].count(); 123 printf("%d\n",ans); 124 } 125 } 126 return 0; 127 }

1228

被折叠的 条评论
为什么被折叠?



