动态逆序对[CDQ分治]

题面
luogu

cdq分治入门
注意删的是值不是位置!


#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int N = 1e5 + 5;
const int inf = 0x3f3f3f3f;
struct Node{
    int x, y, z;
    long long cnt;
}node[N];
inline bool rule_xyz(Node x, Node y){
    if(x.x != y.x) return x.x < y.x;
    if(x.y != y.y) return x.y < y.y;
    return x.z < y.z;
}
inline bool rule_yzx(Node x, Node y){
    if(x.y != y.y) return x.y < y.y;
    if(x.z != y.z) return x.z < y.z;
    return x.x < y.x;
}
int n, m, a[N], b[N];

inline void debug(int L, int R){
    for(int i = L; i <= R; ++i){
        if(node[i].x == 1){
            printf("debug %lld\n", node[i].cnt);
            break;  
        }   
    }   
}

struct BIT{
    int w[N];
    void ins(int x, int d){
        while(x <= n){w[x] += d; x += x & -x;}
    }
    int qry(int x){
        int res = 0;
        while(x){res += w[x]; x -= x & -x;}
        return res;
    }
    void print(){
        for(int i = 1; i <= n; ++i) printf("%d ", w[i]);
        printf("\n");   
    }
}bit;

void cdq(int L, int R){
    if(L >= R) return ;
    int mid = L + ((R - L) >> 1);
    cdq(L, mid); cdq(mid + 1, R);   
    sort(node + L, node + mid + 1, rule_yzx);
    sort(node + mid + 1, node + R + 1, rule_yzx);
    int j = mid + 1;
    for(int i = L; i <= mid; ++i){
        while(j <= R && node[j].y < node[i].y){
            bit.ins(node[j].z, 1); ++j;
        } 
        node[i].cnt += bit.qry(n) - bit.qry(node[i].z);
    }
    while(--j >= mid + 1){bit.ins(node[j].z, -1);}
    
    j = R;
    for(int i = mid; i >= L; --i){
        while(j >= mid + 1 && node[j].y > node[i].y){
            bit.ins(node[j].z, 1); --j;
        }
        node[i].cnt += bit.qry(node[i].z - 1);
    }
    while(++j <= R) {bit.ins(node[j].z, -1);}
    //printf("%d %d\n", L, R); 
    //bit.print();
    //if(L <= 1) debug(L, R);
}

int main(){
    //freopen();
    scanf("%d%d", &n, &m); 
    for(int i = 1; i <= n; ++i){
        scanf("%d", &a[i]);
        b[a[i]] = i;    
    }
    for(int i = 1; i <= n; ++i) 
        node[i] = (Node){inf, i, a[i], 0};  
    for(int i = 1, x; i <= m; ++i){
        scanf("%d", &x);
        node[b[x]].x = i;//注意审题哦 这里是删掉为x的值
    } 
    
    sort(node + 1, node + n + 1, rule_xyz);
    cdq(1, n);
    sort(node + 1, node + n + 1, rule_xyz);
    
    long long ans = 0;
    for(int i = n; i >= 1; --i){
        ans += bit.qry(a[i]);
        bit.ins(a[i], 1);
    }
    for(int i = 1; i <= m; ++i){
        printf("%lld\n", ans);
        ans -= node[i].cnt;
    }
    return 0;   
}

转载于:https://www.cnblogs.com/hjmmm/p/10647447.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值