【LG1393】动态逆序对

【LG1393】动态逆序对

题面

洛谷

题解

\(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 = 40005; 
struct Node { int x, y, z, s; } t[MAX_N]; 
bool cmp_x(Node a, Node b) { return a.x < b.x; } 
bool cmp_y(Node a, Node b) { return a.y < b.y; } 
int N, M, ans, X[MAX_N], a[MAX_N], b[MAX_N], c[MAX_N], d[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; 
	Div(l, mid); Div(mid + 1, r); 
	int j = mid + 1; 
	for (int i = l; i <= mid; i++) { 
	    for ( ; j <= r && t[j].y < t[i].y; ) add(t[j].z, 1), ++j; 
	    t[i].s += sum(N) - sum(t[i].z); 
    } 
    for (int i = mid + 1; i < j; i++) add(t[i].z, -1); 
    j = r; 
    for (int i = mid; i >= l; i--) { 
        for ( ; j > mid && t[j].y > t[i].y; ) add(t[j].z, 1), --j; 
        t[i].s += sum(t[i].z - 1); 
    } 
    for (int i = r; i > j; i--) add(t[i].z, -1); 
    inplace_merge(&t[l], &t[mid + 1], &t[r + 1], cmp_y); 
} 
int main () {  
    N = gi(), M = gi(); 
    for (int i = 1; i <= N; i++) X[i] = a[i] = gi(); 
    sort(&X[1], &X[N + 1]); 
    for (int i = 1; i <= N; i++) a[i] = lower_bound(&X[1], &X[N + 1], a[i]) - X; 
    for (int i = N; i >= 1; i--) ans += sum(a[i] - 1), add(a[i], 1); 
    for (int i = 1; i <= N; i++) t[i].x = N + 1, t[i].y = i, t[i].z = a[i]; 
    for (int i = 1; i <= M; i++) { 
        d[i] = gi(); 
        t[d[i]].x = i; 
    } 
    sort(&t[1], &t[N + 1], cmp_x); 
	memset(c, 0, sizeof(c)); 
	Div(1, N); 
	for (int i = 1; i <= N; i++) c[t[i].y] = t[i].s; 
	printf("%d ", ans); 
	for (int i = 1; i <= M; i++) printf("%d ", ans -= c[d[i]]); 
    return 0; 
} 
posted @ 2018-12-14 22:33  heyujun  阅读(170)  评论(0编辑  收藏  举报