分块

  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 }

 

posted @ 2018-07-19 20:08  LeeSongt  阅读(181)  评论(0)    收藏  举报