[YNOI 2016] 掉进兔子洞
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=4939
[算法]
不难发现 ,
ansi = (r1 - l1 + 1) + (r2 - l2 + 1) + (r3 - l3 + 1) - sigma(min(cnt1i , cnt2i , cnt3i))
bitset + 莫队即可
时间复杂度 : O(Nsqrt(N) / 32)
[代码]
#include<bits/stdc++.h> using namespace std; #define N 100010 #define TT 25000 typedef long long ll; typedef long double ld; typedef unsigned long long ull; struct query { int l , r; int id; } q[N]; int n , m , sz; int cnt[N] , block[N] , ans[N] , l1[N] , r1[N] , l2[N] , r2[N] , l3[N] , r3[N] , a[N] , b[N]; bool vis[N]; bitset< N > tmp , f[TT + 5]; template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void add(int x) { tmp[a[x] + cnt[a[x]]] = 1; ++cnt[a[x]]; } inline void dec(int x) { tmp[a[x] + cnt[a[x]] - 1] = 0; --cnt[a[x]]; } inline bool cmp(query a , query b) { if (block[a.l] == block[b.l]) return a.r < b.r; else return a.l < b.l; } inline void solve(int l , int r) { tmp.reset(); memset(cnt , 0 , sizeof(cnt)); memset(vis , false , sizeof(vis)); int len = 0; for (int i = 1; i <= TT; i++) f[i].reset(); for (int i = l; i <= r; i++) { q[++len] = (query){l1[i] , r1[i] , i}; ans[i] += r1[i] - l1[i] + 1; q[++len] = (query){l2[i] , r2[i] , i}; ans[i] += r2[i] - l2[i] + 1; q[++len] = (query){l3[i] , r3[i] , i}; ans[i] += r3[i] - l3[i] + 1; } sort(q + 1 , q + len + 1, cmp); int L = q[1].l , R = q[1].l - 1; for (int i = 1; i <= len; i++) { while (R < q[i].r) { add(R + 1); ++R; } while (R > q[i].r) { dec(R); --R; } while (L < q[i].l) { dec(L); ++L; } while (L > q[i].l) { add(L - 1); --L; } if (!vis[q[i].id - l + 1]) { vis[q[i].id - l + 1] = true; f[q[i].id - l + 1] = tmp; } else f[q[i].id - l + 1] &= tmp; } for (int i = l; i <= r; i++) ans[i] -= f[i - l + 1].count() * 3; } int main() { read(n); read(m); int size = (int)sqrt(n) + 1; for (int i = 1; i <= n; i++) block[i] = (i - 1) / size + 1; for (int i = 1; i <= n; i++) { read(a[i]); b[i] = a[i]; } sort(b + 1 , b + n + 1); for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1 , b + n + 1 , a[i]) - b; for (int i = 1; i <= m; i++) { read(l1[i]); read(r1[i]); read(l2[i]); read(r2[i]); read(l3[i]); read(r3[i]); } for (int i = 1; i <= m; i += TT) solve(i , min(i + TT - 1 , m)); for (int i = 1; i <= m; i++) printf("%d\n" , ans[i]); return 0; }