题目链接:这里

解法:树套树 和 CDQ不会写,分块暴力大法好。

我们可以把原序列a[]分成个块,每个块有个数。然后维护一个b[],b[]中的每一个块都是一个单调递增的序列。

当前要删除的数为x,所在的块是k,那我们分两种情况做:

1.对于k号块,直接在a[]的k号块中枚举求逆序对,复杂度为。

2.对于除了k号块以外的每一个块,利用b[]二分求x在当前块中产生的逆序对数,复杂度为O(nsqrt(n))

然后删除这个数,把b[]中相对应的数变为0,把这个块重新排序。

因为我们要保证每个块的大小不变,并且每个数所在的块的编号也不变,所以我们在删除的时候不能直接删除。

既然不能直接删除,我们就得搞一些东西来维护。

在计算第一步的时候,我们开一个bool数组f[i],表示i这个数有没有被删掉,然后枚举的时候判断一下。

在计算第二步的时候,我们开一个数组sum[],sum[i]表示第i个块里删除了多少个数。这样的话,如果我们在计算的时候这个

块里产生了t对逆序对,而已经被删除的数都变成0,所以每个0都会产生一个逆序对,那么不算上已经被删除的实际只有

t-sum[i]个逆序对。

然后就做完啦。

///BZOJ 3295 动态逆序对

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
//LL ans;
const int maxn = 200010;
int n, m, x, y, num, block, a[maxn], b[maxn], tmp[maxn], belong[maxn], l[maxn], r[maxn], sum[maxn], id[maxn];
bool f[maxn];
LL ans;
int c[maxn];
inline int lowbit(int x){
    return x&-x;
}
void add(int x, int v){
    for(int i=x; i<=n; i+=lowbit(i)) c[i]+=v;
}
int query(int x){
    int res=0;
    for(int i=x; i; i-=lowbit(i)) res+=c[i];
    return res;
}
void init(){
    scanf("%d %d", &n,&m);
    block = sqrt(n);
    num = n/block;
    if(n%block) num++;
    for(int i=1; i<=num; i++) l[i]=(i-1)*block+1,r[i]=i*block;
    r[num]=n;
    for(int i=1; i<=n; i++) belong[i]=(i-1)/block+1;
    for(int i=1; i<=n; i++) scanf("%d", &a[i]), tmp[i]=a[i], id[a[i]]=i;
    ans = 0;
    for(int i=1; i<=n; i++){
        add(a[i],1);
        ans+=1LL*(i-query(a[i]));
    }
    for(int i=1; i<=n; i++) b[i]=a[i];
    for(int i=1; i<=num; i++) sort(b+l[i],b+r[i]+1);
    for(int i=1; i<=n; i++) f[i]=1,sum[i]=0;
}
int query2(int pos, int val){
    int low, high, ret;
    low = l[pos];
    high = r[pos];
    ret = r[pos];
    while(low <= high){
        int mid = (low+high)/2;
        if(b[mid]<=val) ret=mid,low=mid+1;
        else high=mid-1;
    }
    if(b[ret]>val) return l[pos]-1;
    else return ret;
}
int main()
{
    init();
    while(m--){
        printf("%lld\n", ans);
        scanf("%d", &y);
        x = id[y];
        int k = belong[x];
        for(int i=1; i<k; i++){
            ans-=(r[i]-query2(i,a[x]));
        }
        for(int i=k+1; i<=num; i++){
            ans-=query2(i,a[x])-l[i]+1-sum[i];
        }
        for(int i=l[k]; i<x; i++){
            if(f[a[i]]&&a[i]>a[x]) ans--;
        }
        for(int i=x+1; i<=r[k]; i++){
            if(f[a[i]]&&a[i]<a[x]) ans--;
        }
        int pos = query2(k,a[x]);
        b[pos]=0;
        sum[k]++;
        f[a[x]]=0;
        sort(b+l[k],b+r[k]+1);
    }
    return 0;
}