动态逆序对

CDQ分治
把删除转变为逐个添加,于是就变成了三维偏序问题
时间,位置,大小
分两遍统计即可

# include 
# include 
# include 
# include 
# include 
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;

IL ll Read(){
    RG char c = getchar(); RG ll x = 0, z = 1;
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + c - '0';
    return x * z;
}

const int MAXN(100010);
int n, a[MAXN], id[MAXN], vis[MAXN], m, del[MAXN];
ll ans[MAXN], t[MAXN];
struct Point{
    int a, b, c;
    ll ans;
    IL bool operator <(RG Point B) const{  return a < B.a;  }
} p[MAXN], q[MAXN];

IL void Add(RG int x, RG int d){  for(; x <= n; x += x & -x) t[x] += d;  }

IL int Query(RG int x){  RG int cnt = 0; for(; x; x -= x & -x) cnt += t[x]; return cnt;  } 

IL void CDQ(RG int l, RG int r){
    if(l == r) return;
    RG int mid = (l + r) >> 1, le = 0; CDQ(l, mid); CDQ(mid + 1, r);
    for(RG int i = l, j = mid + 1, len = l; i <= mid || j <= r; )
        if(j > r || (i <= mid && p[i].b < p[j].b)) q[len++] = p[i++];
        else q[len++] = p[j++];
    for(RG int i = l; i <= r; i++) p[i] = q[i];
    for(RG int i = l; i <= r; i++)
        if(p[i].a <= mid) Add(p[i].c, 1), le++;
        else p[i].ans += le - Query(p[i].c);
    for(RG int i = l; i <= r; i++)
        if(p[i].a <= mid) Add(p[i].c, -1);
    for(RG int i = r; i >= l; i--)
        if(p[i].a <= mid) Add(p[i].c, 1);
        else p[i].ans += Query(p[i].c);
    for(RG int i = r; i >= l; i--)
        if(p[i].a <= mid) Add(p[i].c, -1);
}

int main(RG int argc, RG char* argv[]){
    n = Read(); m = Read(); RG int cnt = 0;
    for(RG int i = 1; i <= n; i++) a[i] = Read(), id[a[i]] = i;
    for(RG int i = 1; i <= m; i++) del[i] = Read(), vis[id[del[i]]] = 1;
    for(RG int i = 1; i <= n; i++) if(!vis[i]) p[++cnt] = (Point){cnt, i, a[i]};
    for(RG int i = m; i; i--) p[++cnt] = (Point){cnt, id[del[i]], del[i]};
    CDQ(1, n);
    sort(p + 1, p + n + 1);
    for(RG int i = 1; i <= n; i++) ans[i] = ans[i - 1] + p[i].ans;
    for(RG int i = n; i > n - m; i--) printf("%lld\n", ans[i]);
    return 0;
}

转载于:https://www.cnblogs.com/cjoieryl/p/8206376.html

你可能感兴趣的:(动态逆序对)