我们可以按上图所画的方法算每个边的贡献。
如果答案点在线段上:贡献为x1 + x2
如果答案在线段外:贡献为x1 + x2 + x3 * 2
这里x3就是这道题要的贡献答案
我们会惊奇的发现这和原题所求的贡献之间的关系为:原题答案 = (上述答案 - 线段长度)/ 2.
现在题目所求的min值就是我们上面改编算贡献的答案的(min值-所有线段的长度)/ 2.
我们可以发现答案点的左边和右边的线段端点数一定相等。(这个性质用改编过后算贡献的方法比较好得出)。
所以我们用两个优先队列维护两边的端点数相等,算答案的方式挺多的大家可以自己试试。
这道题的难点就是要推出答案点左右端点数相等。
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define edl '\n'
ll n,ans,l,r;
priority_queue<ll, vector<ll>, less<ll>> ql;
priority_queue<ll, vector<ll>, greater<ll>> qr;
void Solve()
{
ans = 0;
cin >> n;
cin >> l >> r;
ql.push(l);
qr.push(r);
cout << 0 << edl;
for(int i = 2; i <= n; i++)
{
cin >> l >> r;
if(r < ql.top())
{
ans += ql.top() - r;
qr.push(ql.top());
ql.pop();
ql.push(l);
ql.push(r);
}
else if(l > qr.top())
{
ans += l - qr.top();
ql.push(qr.top());
qr.pop();
qr.push(l);
qr.push(r);
}
else
{
ql.push(l);
qr.push(r);
}
cout << ans << edl;
}
}
int main()
{
ios_base::sync_with_stdio(false), cin.tie(0);
int t = 1;
//cin >> t;
while(t--)
Solve();
return 0;
}