1. 程式人生 > >bzoj 3236 [Ahoi2013]作業 莫隊+樹狀數組

bzoj 3236 [Ahoi2013]作業 莫隊+樹狀數組

owb \n emp line ahoi2013 uniq str oid 樹狀

題面

題目傳送門

解法

離線詢問,然後莫隊

建2棵權值樹狀數組,一棵為區間有多少個數,另一棵為區間有多少個不同的數

在擴展區間的時候用樹狀數組修改即可

代碼

#include <bits/stdc++.h>
#define N 3000010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f;
}
int n, m, len, a[N], c[N], col[N], cnt[N], ans[N][2];
struct Node {
    int l, r, x, y, id;
} b[N];
struct BIT {
    int f[N];
    int lowbit(int x) {return x & -x;}
    void modify(int x, int v) {
        for (int i = x; i <= len; i += lowbit(i))
            f[i] += v;
    }
    int query(int x) {
        int ret = 0;
        for (int i = x; i; i -= lowbit(i))
            ret += f[i];
        return ret;
    }
} T1, T2;
bool cmp(Node a, Node b) {
    return col[a.l] == col[b.l] ? a.r < b.r : a.l < b.l;
}
void update(int x, int v) {
    cnt[a[x]] += v; T1.modify(a[x], v);
    if (v == 1)
        if (cnt[a[x]] == 1) T2.modify(a[x], 1);
    if (v == -1)
        if (!cnt[a[x]]) T2.modify(a[x], -1);
}
main() {
    read(n), read(m); len = 0;
    for (int i = 1; i <= n; i++)
        read(a[i]), c[++len] = a[i];
    int siz = (int)sqrt(n);
    for (int i = 1; i <= n; i++) col[i] = (i + siz - 1)  / siz;
    for (int i = 1; i <= m; i++) {
        read(b[i].l), read(b[i].r), read(b[i].x), read(b[i].y), b[i].id = i;
        c[++len] = b[i].x, c[++len] = b[i].y;
    }
    sort(c + 1, c + len + 1);
    len = unique(c + 1, c + len + 1) - c - 1;
    map <int, int> h;
    for (int i = 1; i <= len; i++) h[c[i]] = i;
    for (int i = 1; i <= n; i++) a[i] = h[a[i]];
    for (int i = 1; i <= m; i++)
        b[i].x = h[b[i].x], b[i].y = h[b[i].y];
    sort(b + 1, b + m + 1, cmp);
    for (int i = 1, l = 1, r = 0; i <= m; i++) {
        while (r < b[i].r) update(++r, 1);
        while (r > b[i].r) update(r--, -1);
        while (l < b[i].l) update(l++, -1);
        while (l > b[i].l) update(--l, 1);
        ans[b[i].id][0] = T1.query(b[i].y) - T1.query(b[i].x - 1);
        ans[b[i].id][1] = T2.query(b[i].y) - T2.query(b[i].x - 1);
    }
    for (int i = 1; i <= m; i++)
        cout << ans[i][0] << ‘ ‘ << ans[i][1] << "\n";
    return 0;
}

bzoj 3236 [Ahoi2013]作業 莫隊+樹狀數組