zoukankan      html  css  js  c++  java
  • [国家集训队]排队

    分块套平衡树即可。

    当然里面的平衡树由于只需要支持插入删除和询问某一段值域的值的个数可以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;
    }
    
  • 相关阅读:
    RabbitMQ死信队列另类用法之复合死信
    Asp.NetCore轻松学-使用Docker进行容器化托管
    Asp.NetCore轻松学-使用Supervisor进行托管部署
    Asp.NetCore轻松学-部署到 Linux 进行托管
    Asp.NetCore轻松学-部署到 IIS 进行托管
    一个提问引发的职业规划热议-拨开迷雾,走向光明
    Asp.Net Core 轻松学-使用MariaDB/MySql/PostgreSQL和支持多个上下文对象
    Asp.Net Core 轻松学-经常使用异步的你,可能需要看看这个文章
    Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库
    Asp.Net Core 轻松学-多线程之Task(补充)
  • 原文地址:https://www.cnblogs.com/LiM-817/p/11913383.html
Copyright © 2011-2022 走看看