1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #define maxn 100010 #define maxs 400 using namespace std;
int n, m, a[maxn];
int blo, num, cnt[maxn], d[maxs], D[maxs], bl[maxn], l[maxs], r[maxs]; void init_blo() { blo = sqrt(n); num = (n + blo - 1) / blo; for (int i = 1; i <= num; ++i) { l[i] = (i - 1) * blo + 1; r[i] = i * blo; } r[num] = n; for (int i = 1; i <= n; ++i) bl[i] = (i - 1) / blo + 1; }
inline void add(int v) { ++cnt[v]; ++d[bl[v]]; if (cnt[v] == 1) ++D[bl[v]]; }
inline void del(int v) { --cnt[v]; --d[bl[v]]; if (cnt[v] == 0) --D[bl[v]]; }
pair<int, int> query(int L, int R) { int s1 = 0, s2 = 0, Bl = bl[L], Br = bl[R]; if (Bl == Br) { for (int i = L; i <= R; ++i) s1 += cnt[i], s2 += cnt[i] > 0; return { s1, s2 }; } for (int i = Bl + 1; i < Br; ++i) s1 += d[i], s2 += D[i]; for (int i = L; i <= r[Bl]; ++i) s1 += cnt[i], s2 += cnt[i] > 0; for (int i = l[Br]; i <= R; ++i) s1 += cnt[i], s2 += cnt[i] > 0; return { s1, s2 }; }
struct Query { int l, r, a, b, id;
friend bool operator < (const Query &u, const Query &v) { if (u.l / blo == v.l / blo) return u.l / blo & 1 ? u.r < v.r : u.r > v.r; return u.l < v.l; } } Q[maxn];
pair<int, int> ans[maxn]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m; init_blo(); for (int i = 1; i <= n; ++i) cin >> a[i]; for (int i = 1; i <= m; ++i) cin >> Q[i].l >> Q[i].r >> Q[i].a >> Q[i].b, Q[i].id = i; sort(Q + 1, Q + m + 1); int l = Q[1].l, r = l - 1; for (int i = 1; i <= m; ++i) { while (r < Q[i].r) add(a[++r]); while (l > Q[i].l) add(a[--l]); while (r > Q[i].r) del(a[r--]); while (l < Q[i].l) del(a[l++]); ans[Q[i].id] = query(Q[i].a, Q[i].b); } for (int i = 1; i <= m; ++i) cout << ans[i].first << " " << ans[i].second << "\n"; return 0; }
|