思路:sqrt(n)分块+bitset优化
第一次写分块,以此纪念
参考代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<sstream>
#include<string>
#include<bitset>
using namespace std;
typedef long long LL;
const LL LINF = (1LL <<63);
const int INF = 1 << 31;
const int NS = 100010;
const int MS = 320;
const int MOD = 1000000007;
const int KS = 5;
struct node{
int id;
int v;
bool operator < (const node &cmp)const
{
return v < cmp.v;
}
};
struct scorelist{
int len;
node s[NS];
int getPos(int key)
{
node tmp;
tmp.v = key;
int pos = upper_bound(s, s + len, tmp) - s;
return pos;
int mid;
int l = 0, r = len - 1;
if(s[r].v <= key) return len;
while(l < r)
{
mid = (l + r) >> 1;
if(key >= s[mid].v)
{
l = mid + 1;
}
else
{
r = mid;
}
}
return r;
}
}L[KS];
bitset<NS> sco[KS][MS];
bitset<NS> cnt[KS];
int n, m, num;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
int nCase, T;
scanf("%d", &nCase);
for(int T = 1; T <= nCase; T++)
{
// printf("T = %d\n", T);
scanf("%d %d", &n, &m);
num = int(sqrt(1.0 * n));
if(num <= 0) num = 1;
for(int i = 0; i < n; i++)
{
for(int k = 0; k < KS; k++)
{
L[k].s[i].id = i;
scanf("%d", &L[k].s[i].v);
}
}
int pos, id;
int maxpos = 0;
for(int k = 0; k < KS; k++)
{
L[k].len = n;
sort(L[k].s, L[k].s + n);
// printf("arr[%d] =", k);
// for(int i = 0; i < n; i++)
// {
// printf(" %d", L[k].s[i].v);
// }
// puts("");
for(int i = 0; i < n; i++)
{
pos = i / num;
if(pos > maxpos)
{
maxpos = pos;
}
if(0 == (i % num))
{
sco[k][pos].reset();
if(pos > 0)
{
sco[k][pos] = sco[k][pos - 1];
}
}
id = L[k].s[i].id;
sco[k][pos][id] = 1;
}
}
int q, lim, last = 0;
node qu[MS];
scanf("%d", &q);
while(q--)
{
for(int k = 0; k < KS; k++)
{
scanf("%d", &qu[k].v);
qu[k].v ^= last;
lim = L[k].getPos(qu[k].v);
cnt[k].reset();
if(n == lim)
{
cnt[k] = sco[k][maxpos];
}
else
{
if(0 == (lim % num))
{
pos = int(lim / num);
pos --;
if(pos >= 0)
{
cnt[k] = sco[k][pos];
}
}
else
{
pos = int((lim - 1) / num);
if(pos > 0)
{
cnt[k] = sco[k][pos - 1];
}
for(int j = pos * num; j < lim; j++)
{
id = L[k].s[j].id;
cnt[k][id] = 1;
}
}
}
// cout<<"lim = "<<lim<<" cnt["<<k<<"] = "<<cnt[k].to_string()<<endl;
}
for(int k = 1; k < KS; k++)
{
cnt[0] &= cnt[k];
}
last = cnt[0].count();
printf("%d\n", last);
}
}
return 0;
}
/*
2
4 8
1 1 1 1 1
2 2 2 2 2
1 2 3 4 5
5 4 3 2 1
2
1 1 1 1 1
3 3 3 3 3
5 8
1 1 1 1 1
2 2 2 2 2
1 2 3 4 5
5 4 3 2 1
3 3 3 3 3
6
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
5 5 5 5 5
1 2 3 4 5
5 4 3 2 1
*/