题解 超脑星球

传送门

这题其实可以费用流但并没有想到

  • 存在最佳匹配/带有每个位置最多放一个的限制时,暴力可以考虑费用流

首先发现若将 b 数组排序,贪心从两边选一定更优
将 a 数组相邻元素看成值域上的一条线段
但是发现新加入的数可能使原来形成的数失配,一旦形成连锁反应就 \(n^2\)
其实如果这么写了因为其实没有连锁反应一样可以过
至于为什么没有连锁反应可以反证一下
于是四种加入情况分别讨论一下

\[mn-p_l \]

\[p_r-mx \]

\[mn-p_l-(p_r'-mx)+(p_r'-mx') \]

\[(p_r-mx)-(mx-p_l')+(mn'-p_l') \]

于是将其中的变量拆出来用堆维护即可
复杂度 \(O(nlogn)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define fir first
#define sec second
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
ll ans;
bool del[N];
int a[N], b[N];
pair<int, int> line[N];
priority_queue<pair<int, int>, vector<pair<int, int>>, less<pair<int, int>>> q1, q3;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q2, q4;

signed main()
{
	freopen("brain.in", "r", stdin);
	freopen("brain.out", "w", stdout);
	
	n=read(); m=read();
	for (int i=1; i<=n; ++i) a[i]=read();
	for (int i=1; i<=m; ++i) b[i]=read();
	for (int i=2,mx,mn; i<=n; ++i) {
		mx=max(a[i-1], a[i]);
		mn=min(a[i-1], a[i]);
		q1.push({mn, i}); q2.push({mx, i});
		line[i]={mn, mx}; ans+=mx-mn;
		// cout<<"line: "<<mn<<' '<<mx<<endl;
	}
	// cout<<"ans: "<<ans<<endl;
	sort(b+1, b+m+1);
	// cout<<"b: "; for (int i=1; i<=m; ++i) cerr<<b[i]<<' '; cerr<<endl;
	int p1=1, p2=m;
	for (int i=1; i<=m; ++i) {
		// cerr<<endl;
		// cerr<<"i: "<<i<<endl;
		int mx=0;
		while (q1.size()&&del[q1.top().sec]) q1.pop();
		while (q2.size()&&del[q2.top().sec]) q2.pop();
		if (q1.size()) mx=max(mx, q1.top().fir-b[p1]);
		if (q2.size()) mx=max(mx, b[p2]-q2.top().fir);
		if (q3.size()&&q2.size()) mx=max(mx, q3.top().fir-b[p1]-q2.top().fir);
		if (q4.size()&&q1.size()) mx=max(mx, b[p2]-q4.top().fir+q1.top().fir);
		ans+=2*mx;
		// cerr<<"mx: "<<mx<<endl;
		// cerr<<"bp: "<<b[p1]<<' '<<b[p2]<<endl;
		// cerr<<"size: "<<q1.size()<<' '<<q2.size()<<' '<<q3.size()<<' '<<q4.size()<<endl;
		if (q1.size() && mx==q1.top().fir-b[p1]) {
			// cerr<<"choose: "<<1<<endl;
			q4.push({line[q1.top().sec].fir+line[q1.top().sec].sec, q1.top().sec});
			del[q1.top().sec]=1; q1.pop(); ++p1;
		}
		else if (q2.size() && mx==b[p2]-q2.top().fir) {
			// cerr<<"choose: "<<2<<endl;
			// cerr<<b[p2]<<' '<<q2.top().fir<<endl;
			q3.push({line[q2.top().sec].fir+line[q2.top().sec].sec, q2.top().sec});
			del[q2.top().sec]=1; q2.pop(); --p2;
		}
		else if (q3.size()&& mx==q3.top().fir-b[p1]-(q2.size()?q2.top().fir:0)) {
			// cerr<<"choose: "<<3<<endl;
			q4.push(q3.top()); q3.pop(); ++p1;
			if (q2.size()) q3.push({line[q2.top().sec].fir+line[q2.top().sec].sec, q2.top().sec}), del[q2.top().sec]=1, q2.pop();
		}
		else if (q4.size()&& mx==b[p2]-q4.top().fir+(q1.size()?q1.top().fir:0)) {
			// cerr<<"choose: "<<4<<endl;
			q3.push(q4.top()); q4.pop(); --p2;
			if (q1.size()) q4.push({line[q1.top().sec].fir+line[q1.top().sec].sec, q1.top().sec}), del[q1.top().sec]=1, q1.pop();
		}
		else assert(!mx);
		printf("%lld ", ans);
		// cerr<<ans<<' ';
	}
	printf("\n");

	return 0;
}
posted @ 2022-01-16 07:28  Administrator-09  阅读(0)  评论(0编辑  收藏  举报