AtCoder Beginner Contest 127 F - Absolute Minima(对顶堆求动态中位数)

题目链接:F - Absolute Minima (atcoder.jp)

题目大意,给出操作次数Q,完成Q次操作。

共两种操作:

        操作1:输入 1 a b ,将 f(x) 替换为 f(x) + | x - a | + b;

        操作2:输入 2,找出最小的 x 使得 f(x) 的值最小;


我们可以发现 | x - a | 可以抽象成位置 x 与位置 a 之间的距离,而 b 并不会受到 x 变化的影响。所以我们只需要距离已存在的位置 a 中距离其他点距离之和最小就可以了,很明显的可以看出 这个 a 是所有点中距离中位数最近的点。但是操作1会改变序列 a 的中位数,所以我们需要对顶堆来实现动态中位数的求解。

#include<bits/stdc++.h>
using namespace std;

#define Pqueue priority_queue
#define lc p<<1
#define rc p<<1|1
#define IOS ios::sync_with_stdio(false),cin.tie(0);
#define fi first
#define se second

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<ll, ll> PII;

const int mod = 998244353;
const int N = 1e6 + 10;
const ld eps = 1e-9;
const ll inf = 0x3f3f3f3f;
const ll P = 131;

/*****************************华丽的分割线*****************************/
priority_queue<ll, vector<ll>, greater<ll>> minq;    //小根堆
priority_queue<ll> maxq;    //大根堆
ll sum1, sum2;    //大根堆中的总和与小根堆中的总和

void insert(ll num) {        //操作1
	if (minq.size() >= maxq.size() || maxq.empty()) {
		sum1 += num;
		minq.push(num);
		maxq.push(minq.top());
		sum1 -= minq.top();
		sum2 += minq.top();
		minq.pop();
	} else {
		sum2 += num;
		maxq.push(num);
		minq.push(maxq.top());
		sum2 -= maxq.top();
		sum1 += maxq.top();
		maxq.pop();
	}
}

void solve() {
	ll q, tot = 0;
	cin >> q;
	while (q--) {
		int op;
		cin >> op;
		if (op == 1) {
			ll a, b;
			cin >> a >> b;
			insert(a);
			tot += b;    //对b的迭加
		} else {
			ll siz = maxq.size() - minq.size();    //多出的x的个数
			cout << maxq.top() << " " << siz*maxq.top() + sum1 - sum2 + tot << "\n";
		}
	}
}

int main() {
	IOS
	int T = 1;
	//cin>>T;
	while (T--)
		solve();
	return 0;
}

/*
oxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxox
x                                                                                      o
o       _/_/_/_/                                                              _/       x
x      _/                                                                              o
o     _/_/_/_/ _/  _/_/   _/_/   _/_/_/ _/_/   _/_/_/     _/_/    _/_/_/    _/ _/   _/ x
x    _/       _/_/     _/    _/ _/   _/   _/  _/    _/ _/    _/  _/    _/  _/   _/ _/  o
o   _/       _/       _/    _/ _/   _/   _/  _/    _/ _/    _/  _/    _/  _/    _/_/   x
x  _/       _/         _/_/   _/   _/   _/  _/_/_/     _/_/ _/ _/    _/  _/      _/    o
o                                          _/                           _/      _/     x
x                                         _/                        _/_/       _/      o
o                                                                                      x
xoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxo
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

panjyash

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值