P4688 [Ynoi2016]掉进兔子洞
https://www.luogu.org/problemnew/show/P4688
分析:
莫队+bitset。
一个询问的答案就是 (r1-l1+1) + (r2-l2+1) + (r3-l3+1) - 三个区间都有的元素的个数。
前面一块可以直接求,后面的考虑莫队。我们可以用bitset来实现查询三个区间都出现的个数。但是每个区间内不保证数字都不一样,如果出现了相同的数字,可以依次在bitset中排开,例如12223,在bitset中的坐标就是12345,所以在离散化的时候只要不去重就行了,然后在增加删除一个数的时候,这个数的位置就是离散化后的坐标+前面有多少相同的数。注意,区间的位置移动的时候,要先加再减,如果先减,可能先使cnt变成了负数,然后再变成正数,那么birset可能访问无效内存,从而使得RE。
然后发现空间可能会MLE,于是考虑分块处理询问,每个处理询问25000个,然后处理4次。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #include<bitset> 12 using namespace std; 13 typedef long long LL; 14 15 inline int read() { 16 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 17 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 18 } 19 20 const int N = 100000; 21 const int T = 25000; 22 23 int a[N + 5], b[N + 5], bel[N + 5], cnt[N + 5], ans[T + 5]; 24 bool vis[T + 5]; 25 bitset<N + 5> f[T + 5], g; 26 27 struct Que{ 28 int l, r, id; 29 }q[T * 3 + 5]; 30 31 bool cmp(Que A, Que B) { 32 if (bel[A.l] == bel[B.l]) return A.r < B.r; 33 return bel[A.l] < bel[B.l]; 34 } 35 void add(int p) { 36 int x = a[p]; 37 cnt[x] ++; 38 g[x + cnt[x] - 1] = 1; 39 } 40 void del(int p) { 41 int x = a[p]; 42 g[x + cnt[x] - 1] = 0; 43 cnt[x] --; 44 } 45 void solve(int m) { 46 memset(vis, false, sizeof(vis)); 47 memset(ans, 0, sizeof(ans)); 48 memset(cnt, 0, sizeof(cnt)); 49 int n = 0; 50 for (int i=1; i<=m; ++i) { 51 q[++n].id = i, q[n].l = read(), q[n].r = read(); 52 ans[i] += q[n].r - q[n].l + 1; 53 54 q[++n].id = i, q[n].l = read(), q[n].r = read(); 55 ans[i] += q[n].r - q[n].l + 1; 56 57 q[++n].id = i, q[n].l = read(), q[n].r = read(); 58 ans[i] += q[n].r - q[n].l + 1; 59 } 60 sort(q + 1, q + n + 1, cmp); 61 g.reset(); 62 int L = 1, R = 0; 63 for (int i=1; i<=n; ++i) { 64 // 让add在前,如果del在前,可能会使cnt变成负数,使bitset访问无效内存,RE 65 while (L > q[i].l) add(--L); 66 while (R < q[i].r) add(++R); 67 while (L < q[i].l) del(L++); 68 while (R > q[i].r) del(R--); 69 if (!vis[q[i].id]) f[q[i].id] = g, vis[q[i].id] = 1; 70 else f[q[i].id] &= g; 71 } 72 for (int i=1; i<=m; ++i) { 73 ans[i] -= f[i].count() * 3; 74 printf("%d ",ans[i]); 75 } 76 } 77 int main() { 78 int n = read(), m = read(); 79 int B = sqrt(n); 80 81 for (int i=1; i<=n; ++i) a[i] = read(), b[i] = a[i], bel[i] = (i - 1) / B + 1; 82 sort(b + 1, b + n + 1); 83 for (int i=1; i<=n; ++i) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; 84 85 while (m) { 86 if (m < T) solve(m), m = 0; 87 else solve(T), m -= T; 88 } 89 return 0; 90 }