pairing game 杭银理财杯

pairing Game

image

题意是,从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;
}
posted @ 2022-04-04 19:21  指引盗寇入太行  阅读(27)  评论(0编辑  收藏  举报