zoukankan      html  css  js  c++  java
  • P3157 [CQOI2011]动态逆序对

    题意:给一个全排列 按次序删除数 询问每次删除前的逆序个数

    题解:没有删除操作的话 就是普通的树状数组搞了

       带删除的话考虑 类似于带修主席树的操作 树状数组套动态开点权值线段树

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 1e5 + 5;
    
    int n, m, cnt, tot1, tot0;
    int t[MAXN], p[MAXN];
    int sum[MAXN * 400];
    int ls[MAXN * 400], rs[MAXN * 400];
    int tmp[2][50];
    
    void add(int &o, int l, int r, int k, int val) {
        if(!o) o = ++cnt;
        sum[o] += val;
        int mid = l + r >> 1;
        if(l == r) return;
    
        if(k <= mid) add(ls[o], l, mid, k, val);
        else add(rs[o], mid + 1, r, k, val);
    }
    
    void update(int x, int pos, int v) {
        for(int i = x; i <= n; i += (i & -i)) add(t[i], 1, n, pos, v);
    }
    
    void prepare_query(int l, int r) {
        tot1 = tot0 = 0;
        for(int i = r; i >= 1; i -= (i & -i)) tmp[1][++tot1] = t[i];
        for(int i = l; i >= 1; i -= (i & -i)) tmp[0][++tot0] = t[i];
    }
    
    int query(int l, int r, int x, int f) {
        if(l == r) return 0;
        int res = 0;
        int mid = l + r >> 1;
        if(x <= mid) {
            if(f) {
                for(int i = 1; i <= tot1; i++) res += sum[rs[tmp[1][i]]];
                for(int i = 1; i <= tot0; i++) res -= sum[rs[tmp[0][i]]];
            }
            for(int i = 1; i <= tot1; i++) tmp[1][i] = ls[tmp[1][i]];
            for(int i = 1; i <= tot0; i++) tmp[0][i] = ls[tmp[0][i]];
            return res + query(l, mid, x, f);
        } else {
            if(!f) {
                for(int i = 1; i <= tot1; i++) res += sum[ls[tmp[1][i]]];
                for(int i = 1; i <= tot0; i++) res -= sum[ls[tmp[0][i]]];
            }
            for(int i = 1; i <= tot1; i++) tmp[1][i] = rs[tmp[1][i]];
            for(int i = 1; i <= tot0; i++) tmp[0][i] = rs[tmp[0][i]];
            return res + query(mid + 1, r, x, f);
        }
    }
    
    int main() {
        ll ans = 0;
        cnt = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) {
            int x; scanf("%d", &x); p[x] = i;
            prepare_query(0, i - 1);
            ans += 1LL * query(1, n, x, 1);
            update(i, x, 1);
        }
        printf("%lld
    ", ans);
    
        for(int i = 1; i <= m; i++) {
            int x; scanf("%d", &x);
            prepare_query(0, p[x] - 1);
            ans -= 1LL * query(1, n, x, 1);
            //cout << ans <<  " ";
            prepare_query(p[x], n);
            ans -= 1LL * query(1, n, x, 0);
            update(p[x], x, -1);
            if(i != m) printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    How To Change Database Name
    Oracle备份与恢复案例
    Linux 下安装 Oracle9i
    在 Linux x86 上安装 Oracle 数据库 10g_1
    在 Linux x86 上安装 Oracle 数据库 10g_2
    Oracle9i数据库DataGuard实施及维护手册2
    在 Linux x86 上安装 Oracle 数据库 10g_3
    流程企业(钢铁企业)的制造执行系统
    理解和使用Oracle分析工具LogMiner
    Oracle9i数据库Data Guard实施及维护手册 1
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11644349.html
Copyright © 2011-2022 走看看