【LG1975】[国家集训队]排队

【LG1975】[国家集训队]排队

题面

洛谷

题解

又是一个偏序问题
显然\(CDQ\)
交换操作不好弄怎么办?
可以看成两次删除两次插入
排序问题要注意一下
代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector> 
using namespace std;
namespace IO { 
    const int BUFSIZE = 1 << 20; 
    char ibuf[BUFSIZE], *is = ibuf, *it = ibuf; 
    inline char gc() { 
        if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); 
        return *is++; 
    } 
} 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc();
    if (ch == '-') w = -1 , ch = IO::gc();
    while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc();
    return w * data;
} 
const int MAX_N = 22005; 
struct Node { int x, y, z, w, id; } t[MAX_N << 2], tmp[MAX_N << 2]; 
bool cmp_y(Node a, Node b) { return (a.y == b.y) ? (a.z < b.z) : (a.y < b.y); } 
int N, M, tot, X[MAX_N], a[MAX_N], c[MAX_N], ans[MAX_N]; 
inline int lb(int x) { return x & -x; } 
void add(int x, int v) { while (x <= N) c[x] += v, x += lb(x); } 
int sum(int x) { int res = 0; while (x > 0) res += c[x], x -= lb(x); return res; } 
void Div(int l, int r) { 
    if (l == r) return ; 
    int mid = (l + r) >> 1; 
    for (int i = l; i <= r; i++) 
        if (t[i].x <= mid) add(t[i].z, t[i].w); 
        else ans[t[i].id] += t[i].w * (sum(N) - sum(t[i].z)); 
    for (int i = l; i <= r; i++) 
        if (t[i].x <= mid) add(t[i].z, -t[i].w); 
    for (int i = r; i >= l; i--) 
        if (t[i].x <= mid) add(t[i].z, t[i].w); 
        else ans[t[i].id] += t[i].w * sum(t[i].z - 1); 
    for (int i = l; i <= r; i++) if (t[i].x <= mid) add(t[i].z, -t[i].w); 
    int t1 = l - 1, t2 = mid; 
    for (int i = l; i <= r; i++) 
        if (t[i].x <= mid) tmp[++t1] = t[i]; 
        else tmp[++t2] = t[i]; 
    for (int i = l; i <= r; i++) t[i] = tmp[i]; 
    Div(l, mid); Div(mid + 1, r); 
} 
int main () { 
    N = gi(); 
    for (int i = 1; i <= N; i++) X[i] = a[i] = gi(); 
    sort(&X[1], &X[N + 1]); int size = unique(&X[1], &X[N + 1]) - X - 1; 
    for (int i = 1; i <= N; i++) a[i] = lower_bound(&X[1], &X[size + 1], a[i]) - X; 
    for (int i = 1; i <= N; i++) t[++tot] = (Node){tot, i, a[i], 1, 0}; 
    N = size; M = gi(); 
    for (int i = 1; i <= M; i++) { 
        int x = gi(), y = gi(); 
        t[++tot] = (Node){tot, x, a[x], -1, i}; 
        t[++tot] = (Node){tot, y, a[y], -1, i}; 
        t[++tot] = (Node){tot, x, a[y], +1, i}; 
        t[++tot] = (Node){tot, y, a[x], +1, i}; 
        swap(a[x], a[y]); 
    } 
    sort(&t[1], &t[tot + 1], cmp_y); 
    Div(1, tot); 
    printf("%d\n", ans[0]); 
    for (int i = 1; i <= M; i++) printf("%d\n", ans[i] += ans[i - 1]); 
    return 0; 
} 

猜你喜欢

转载自www.cnblogs.com/heyujun/p/10122091.html