zoukankan      html  css  js  c++  java
  • 【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
    ", ans[0]); 
        for (int i = 1; i <= M; i++) printf("%d
    ", ans[i] += ans[i - 1]); 
        return 0; 
    } 
    
  • 相关阅读:
    1月27日 常用函数
    1月25日 JavaScript的DOM操作
    1月25日 JavaScript简介与语法
    1月24日 样式表案例
    5月14日 数字顺序打印并求和
    5月14日 根据班级人数,求平局分,最大值,最小值
    5月14日 九九乘法口诀
    5月14日 打印100以内与7有关的数
    5月14日 函数练习 100以内奇数的和
    5月14日 枚举类型
  • 原文地址:https://www.cnblogs.com/heyujun/p/10122091.html
Copyright © 2011-2022 走看看