P3157 动态逆序对 题解
逆序对的定义 \(\{(i,j)|i<j\and a_i>a_j\}\) 那么这道题目加了时间的一维进去。我们可以想成三维。
对每一个点有一个坐标 \((A_i, B_i, C_i)\)。\(A_i\) 的就是 \(i\),\(B_i\) 就是 \(a_i\),\(C_i\) 就是 \(\text{tim}_i\)。其中 \(\text{tim}_i\) 表示 \(i\) 被删除的时间。
考虑每一个点对答案的贡献,逆序对是对,所以我可以只考察 \(a_i\) 更大的那个,这样不重复不遗漏。
那么假如说对于第 \(i\) 个点,我们肯定要求 \(j>i\) 并且 \(a_i>a_j\) 并且 \(\text{tim}_j\ge\text{tim}_i\)。求出这样的 \(j\) 的个数后那么答案对 \(1\) 到 \(\text{tim}_i-1\) 都会有贡献。
那么这明显是一个 cdq 分治。直接套用 cdq 分治即可。
#include<bits/stdc++.h>
#define rep(I, J, K) for(int I = (int)J; I <= (int)K; ++I)
#define per(I, J, K) for(int I = (int)J; I >= (int)K; --I)
using namespace std;
const int N = 5e5 + 10;
typedef long long ll;
int n, m, a[N], b[N];
ll ans[N];
struct Point {
int x, y, z;
bool operator < (const Point &point) const {
return (y == point.y) ? z > point.z : y < point.y;
}
}p[N];
int tim[N];
struct Fenwick_Tree {
ll val[N];
int lowbit(int x) {return x & -x;}
void insert(int x, int va) {
while(x <= m + 1) {
val[x] += va;
x += lowbit(x);
}
}
int Query(int x) {
if(x < 0) return 0;
int res = 0;
while(x) {
res += val[x];
x -= lowbit(x);
}
return res;
}
int query(int l, int r) {
return Query(r) - Query(l - 1);
}
}bit;
void solve(int l, int r) {
if(l == r) return;
int mid = l + r >> 1;
solve(l, mid); solve(mid + 1, r);
int j = mid + 1;
rep(i, l, mid) {
while(j <= r && p[j].y < p[i].y) bit.insert(p[j].z, 1), ++j;
ll tmp = bit.query(p[i].z, m + 1);
// if(i == 2) cerr << '*' << l << ' ' << r << ' ' << tmp << ' ' << p[i].x << ' ' << p[i].z << ' ' << j << ' ' << p[4].y << ' ' << p[4].z << endl;
ans[1] += tmp, ans[p[i].z + 1] -= tmp;
}
rep(i, mid + 1, j - 1) bit.insert(p[i].z, -1);
int i = mid;
per(j, r, mid + 1) {
while(i >= l && p[i].y > p[j].y) bit.insert(p[i].z, 1), --i;
ll tmp = bit.query(p[j].z + 1, m + 1);
ans[1] += tmp, ans[p[j].z + 1] -= tmp;
}
per(k, mid, i + 1) bit.insert(p[k].z, -1);
sort(p + l, p + r + 1);
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
rep(i, 1, n) cin >> a[i], b[a[i]] = i;
rep(i, 1, m) {
int t;
cin >> t;
tim[t] = i;
}
rep(i, 1, n) if(tim[i] == 0) tim[i] = m;
rep(i, 1, n) p[i] = {i, a[i], tim[a[i]]};
solve(1, n);
rep(i, 1, m) ans[i] += ans[i - 1];
rep(i, 1, m) cout << ans[i] << '\n';
return 0;
}

浙公网安备 33010602011771号