pairing game 杭银理财杯
pairing Game
题意是,从n到1每次删去一对数字,求剩余的相同数字之间的距离
思路:
从1到n开始,每次添加一对数,求出来他们之间已添加的点的数量,同时求出这个点对以前的点产生的贡献,维护三个树状数组
代码:
#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'
const int N = 2000010;
int c[N], c1[N], c2[N];
int l[N], r[N];
#define lowbit(x) x&(-x)
void add(int x, int y, int c[]) {
for (; x < N; x += lowbit(x)) {
c[x] += y;
}
}
int ask(int x, int c[]) {
int res = 0;
for (; x; x -= lowbit(x)) {
res += c[x];
}
return res;
}
void solve(int Case) {
int n;
cin >> n;
for (int i = 1; i <= n * 2; i++) {
int x;
cin >> x;
if (!l[x]) l[x] = i;
else {
r[x] = i;
if (l[x] > r[x]) swap(l[x], r[x]);
}
}
vector<int> res;
res.push_back(0);
int sum = 0;
for (int i = 1; i <= n - 1; i++) {
int L = l[i], R = r[i];
int t = ask(R, c) - ask(L, c);
sum += t;
int x = ask(L, c1), y = ask(L, c2);
sum += (x - y);
x = i - 1 - ask(R, c2), y = i - 1 - ask(R, c1);
sum += (x - y);
res.push_back(sum);
add(L, 1, c1);
add(R, 1, c2);
add(R, 1, c);
add(L, 1, c);
}
reverse(all(res));
for (auto i : res) cout << i << nline;
}
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
//cin >> _; for (Case = 1; Case <= _; Case++)
solve(Case);
return 0;
}