题解 P3157 【[CQOI2011]动态逆序对】CDQ

· · 个人记录

#include <bits/stdc++.h>
constexpr auto Inf = 0x3F3F3F3F;
typedef long long LL;
using namespace std;

namespace IO {
    inline LL read() {
        LL o = 0, f = 1; char c = getchar();
        while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
        while (c > '/' && c < ':') { o = o * 10 + c - '0'; c = getchar(); }
        return o * f;
    }
    inline char recd() {
        char o; while ((o = getchar()) != 'Q' && o < 'D'); return o;
    }
}
using namespace IO;

const int SIZE = 1E5 + 7;

struct _Ask {
    int per, p, w;
    _Ask(int per = 0, int p = 0, int w = 0) : per(per), p(p), w(w) {};
    bool operator < (const _Ask& Tmp) {
        return per < Tmp.per;
    }
} Ask[SIZE << 1], Tmp[SIZE << 1];

int N, M, Ind[SIZE];

LL BIT[SIZE];

void Upd(int pos, int w = 1) {
    while (pos <= N) BIT[pos] += w, pos += pos & -pos;
}

LL Que(int pos) {
    LL ans = 0; while (pos) ans += BIT[pos], pos -= pos & -pos;
    return ans;
}

LL ans[SIZE];

void CDQ(int L, int R) {
    if (L == R) return;
    int M = (L + R) >> 1; CDQ(L, M), CDQ(M + 1, R);
    int Lpos = L, Rpos = M + 1, now = L;

    while (Lpos <= M && Rpos <= R) {
        if (Ask[Lpos].w > Ask[Rpos].w)
            Upd(Ask[Lpos].p), Tmp[now++] = Ask[Lpos++];
        else
            ans[Ask[Rpos].per] += Que(Ask[Rpos].p), Tmp[now++] = Ask[Rpos++];
    }
    while (Lpos <= M)
        Upd(Ask[Lpos].p), Tmp[now++] = Ask[Lpos++];
    while (Rpos <= R)
        ans[Ask[Rpos].per] += Que(Ask[Rpos].p), Tmp[now++] = Ask[Rpos++];
    for (int pos = L; pos <= M; pos++)
        Upd(Ask[pos].p, -1);
    for (int pos = L; pos <= R; pos++)
        Ask[pos] = Tmp[pos];
}

int main() {
    N = read(), M = read();
    for (int pos = 1, w; pos <= N; pos++)
        w = read(), Ask[Ind[w] = pos] = _Ask(0, pos, w);
    int per = N;
    for (int pos = M, w; pos; pos--)
        w = read(), Ask[Ind[w]].per = per--;
    for (int pos = 1; pos <= N; pos++)
        if (!Ask[pos].per) Ask[pos].per = per--;

    sort(Ask + 1, Ask + 1 + N), CDQ(1, N);
    sort(Ask + 1, Ask + 1 + N);
    for (int pos = 1; pos <= N; pos++)
        swap(Ask[pos].p, Ask[pos].w);
    CDQ(1, N);
    for (int pos = 1; pos <= N; pos++) ans[pos] += ans[pos - 1];
    for(int pos = N; pos > N - M; pos--)
        printf("%lld\n", ans[pos]);
}