【题解】LuoGu5687:[CSP-SJX2019]网格图

原题传送门
肯定是让你一排一排的考虑
那就一排一排的考虑

暴力做法就是暴力 k r u s k a l kruskal kruskal,那么怎么把一整排看成一条边?这样就可以满分了
根据 k r u s k a l kruskal kruskal我们可以知道,只要每次选取最小的边还未联通就是最优的
那么就直接一排一排的搞,每次加进来一排值最小的,但是要减去多余的部分(这部分若加入,那么会形成环)

  • 第一次出现横行或列行,全部加
  • 若不是第一次,则看与自己垂直的有几排,只有一排或没有,不会形成环,全加;否则有 x ( x > 1 ) x(x>1) x(x>1)排,则要减去 x − 1 x-1 x1条边

开ll
Code:

#include <bits/stdc++.h>
#define maxn 300010
#define LL long long
using namespace std;
int n, m;
struct node{
	LL x, opt;
}a[maxn << 1];
LL cnt[2];

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) +(c ^ 48);
	return s * w;
}

bool cmp(node x, node y){ return x.x < y.x; }

int main(){
	n = read(), m = read();
	for (int i = 1; i <= n; ++i) a[i] = (node){read(), 0};
	for (int i = n + 1; i <= n + m; ++i) a[i] = (node){read(), 1};
	sort(a + 1, a + 1 + n + m, cmp);
	LL ans = 0;
	for (int i = 1; i <= n + m; ++i){
		LL num = a[i].opt ? n : m;
		if (!cnt[a[i].opt]) ans += (num - 1) * a[i].x;
		else ans += (num - max(1LL, cnt[a[i].opt ^ 1])) * a[i].x;
		++cnt[a[i].opt];
	}
	printf("%lld\n", ans);
	return 0;
}
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页