P2448 无尽的生命

Description

小 a有一个长度无限长的序列 p = (1, 2, 3, 4 ……),初始时 pi = i
给出 m 个操作,每次交换两个位置的数
询问最后序列逆序对的个数

Solution

忘了可以树状数组直接做了.所以写了很麻烦的线段树.
大概写一下怎么做, 因为细节比较多.

首先发现有的数不会被改变也对答案没有影响.有的数虽然会对答案有贡献但是不会被改变.

举个例子:交换2和5位置, 数列变成\(1,5,3,4,2,6,7,\cdots\).
其中1,6, 7,8……这些数不会被改变也没有影响
对于3,4这种数不会被改变但是对答案有影响(和2一起产生逆序对)

  • 对于不会被改变也没有影响的数, 忽略存在就好了.
  • 对于不会被改变但是有影响的数, 这些数的行为表现出来像是一个整体.把他们捆起来变成一个数(只不过影响是这些数的总个数)就好了.

所以就和普通的逆序对求法差不多了.
离散化之后利用树状数组或归并排序或线段树求逆序对.

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e6;
struct Node {
    long long val;
    Node *ls, *rs;
    Node(int _v = 0, Node *_ls = nullptr, Node *_rs = nullptr) :
        val(_v), ls(_ls), rs(_rs) { }
    void pushup() {
        val = ls->val + rs->val;
    }
    void mod(int k) { val += k; }
};
class Tree {
    int n;
    Node* root;
 #define LS l, mid, node->ls
 #define RS mid + 1, r, node->rs
    void build(int l, int r, Node* node) {
        if (l == r) return;
        int mid = l + r >> 1;
        node->ls = new Node();
        node->rs = new Node();
        build(LS), build(RS);
    }
    void insert(int l, int r, Node* node, int p, int k) {
        if (l == r) return node->mod(k);
        int mid = l + r >> 1;
        if (p <= mid) insert(LS, p, k);
        if (p >  mid) insert(RS, p, k);
        node->val = node->ls->val + node->rs->val;
    }
    long long query(int l, int r, Node* node, int L, int R) {
        if (l >= L and r <= R) 
            return node->val;
        int mid = l + r >> 1;
        long long res = 0;
        if (L <= mid) res += query(LS, L, R);
        if (R >  mid) res += query(RS, L, R);
        return res;
    }
  public:
    Tree(int _n) : n(_n), root(new Node()) {}
    void build() {
        build(1, n, root);
    }
    long long query(int l, int r) {
        return query(1, n, root, l, r);
    }
    void insert(int p, int k) {
        insert(1, n, root, p, k);
    }
};
struct Operate {
    int l, r;
    Operate(int _ = 0, int __ = 0) :
        l(_), r(__) {}
}Opt[N];
struct Element {
    int v, siz;
    Element(int _v = 0, int _s = 0) :
        v(_v), siz(_s) { }
    bool operator < (const Element& o) const {
        return v < o.v;
    }
}P[N];

int A[N], seq[N];

int main () {
    int n;
    scanf("%d", &n);
    int tot = 0;
    for (int i = 1, u, v, c; i <= n; i += 1) {
        scanf("%d%d", &u, &v);
        Opt[i] = Operate(u, v);
        A[++tot] = u, A[++tot] = v;
    }
    sort(A + 1, A + tot + 1);
    int cnt = unique(A + 1, A + tot + 1) - A - 1;
    int total = 0;
    for (int i = 1; i <= cnt; i += 1) {
        P[++total] = Element(A[i], 1);
        if (A[i + 1] > A[i] + 1)
            P[++total] = Element(A[i] + 1, A[i + 1] - A[i] - 1);
    }
#define Find(x) lower_bound(P + 1, P + total + 1, Element(x, 0)) - P
    Tree* T = new Tree(total);
    T->build();
    for (int i = 1; i <= total; i += 1)
        seq[i] = i;
    for (int i = 1, u, v; i <= n; i += 1) {
        u = Find(Opt[i].l), v = Find(Opt[i].r);
        swap(seq[u], seq[v]);
    }
    long long res = 0;
    for (int i = 1; i <= total; i += 1) {
        T->insert(seq[i], P[seq[i]].siz);
        res += 1ll * P[seq[i]].siz * T->query(seq[i] + 1, total);
    }
    printf("%lld\n", res);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/qdscwyy/p/9896186.html