[国家集训队]排队

分块套平衡树即可。

当然里面的平衡树由于只需要支持插入删除和询问某一段值域的值的个数可以map树状数组。

(请忽略本次的压行)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 50005, sqr = 300;
int n, a[N], m, t;
LL ans;
map<int, int> cc;
void upd(int v) {
    for (; v <= 1e9; v += (v & -v)) cc[v]++;
}
int qq(int v) {
    int ans1 = 0;
    for (; v; v -= (v & -v)) ans1 += cc[v];
    return ans1;
}
int Lb[sqr], Rb[sqr], pos[N], rt[sqr], ls[N], rs[N], sz[N], rd[N], vl[N], cnt = 0;
int nd(int v) {
    vl[++cnt] = v;
    ls[cnt] = rs[cnt] = 0;
    sz[cnt] = 1;
    return cnt;
}
void pu(int p) { sz[p] = sz[ls[p]] + sz[rs[p]] + 1; }
void split(int p, int& l, int& r, int v) {
    if (!p) {
        l = r = 0;
        return;
    }
    if (vl[p] <= v)
        l = p, split(rs[p], rs[l], r, v);
    else
        r = p, split(ls[p], l, ls[r], v);
    pu(p);
}
void merge(int& p, int l, int r) {
    if (!l || !r) {
        p = l + r;
        return;
    }
    if (rand() % sz[l] < rand() % sz[r])
        p = l, merge(rs[p], rs[l], r);
    else
        p = r, merge(ls[p], l, ls[r]);
    pu(p);
}
void ins(int& r, int v) {
    int a = 0, b = 0;
    split(r, a, b, v), merge(a, a, nd(v)), merge(r, a, b);
}
void del(int& r, int v) {
    int a = 0, b = 0, c = 0;
    split(r, a, b, v), split(a, a, c, v - 1), merge(c, ls[c], rs[c]), merge(a, a, c), merge(r, a, b);
}
int smlthan(int& r, int p) {
    int a = 0, b = 0;
    split(r, a, b, p - 1);
    int as = sz[a];
    merge(r, a, b);
    return as;
}
int bigthan(int& r, int p) {
    int a = 0, b = 0;
    split(r, a, b, p);
    int as = sz[b];
    merge(r, a, b);
    return as;
}
void work() {
    t = (int)sqrt(n);
    for (int i = 1; i <= t; i++) {
        Lb[i] = Rb[i - 1] + 1, Rb[i] = Lb[i] + t - 1;
        for (int j = Lb[i]; j <= Rb[i]; j++) pos[j] = i, ins(rt[i], a[j]);
    }
    if (t * t < n) {
        ++t;
        Lb[t] = Rb[t - 1] + 1;
        Rb[t] = n;
        for (int j = Lb[t]; j <= Rb[t]; j++) pos[j] = t, ins(rt[t], a[j]);
    }
}
void swp(int l, int r) {
    if (pos[l] == pos[r]) {
        int sum = 0;
        for (register int i = l + 1; i <= r - 1; i++) sum += (a[l] > a[i]) + (a[i] > a[r]);
        sum += (a[l] > a[r]);
        ans -= sum;
        swap(a[l], a[r]);
        for (register int i = l + 1; i <= r - 1; i++) ans += (a[l] > a[i]) + (a[i] > a[r]);
        ans += (a[l] > a[r]);
        return;
    }
    int sum = 0;
    for (register int i = l + 1; i <= Rb[pos[l]]; i++) sum += (a[l] > a[i]) + (a[i] > a[r]);
    for (register int i = Lb[pos[r]]; i <= r - 1; i++) sum += (a[l] > a[i]) + (a[i] > a[r]);
    for (register int b = pos[l] + 1; b <= pos[r] - 1; b++)
        sum += smlthan(rt[b], a[l]) + bigthan(rt[b], a[r]);
    sum += (a[l] > a[r]);
    del(rt[pos[l]], a[l]);
    del(rt[pos[r]], a[r]);
    swap(a[l], a[r]);
    ins(rt[pos[r]], a[r]);
    ins(rt[pos[l]], a[l]);
    ans -= sum;
    for (register int i = l + 1; i <= Rb[pos[l]]; i++) ans += (a[l] > a[i]) + (a[i] > a[r]);
    for (register int i = Lb[pos[r]]; i <= r - 1; i++) ans += (a[l] > a[i]) + (a[i] > a[r]);
    for (register int b = pos[l] + 1; b <= pos[r] - 1; b++)
        ans += smlthan(rt[b], a[l]) + bigthan(rt[b], a[r]);
    ans += (a[l] > a[r]);
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    work();
    for (int i = n; i >= 1; i--) {
        ans += qq(a[i] - 1);
        upd(a[i]);
    }
    printf("%lld
", ans);
    scanf("%d", &m);
    while (m--) {
        int l, r;
        scanf("%d%d", &l, &r);
        if (l > r)
            swap(l, r);
        swp(l, r);
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/LiM-817/p/11913383.html