其他分享
首页 > 其他分享> > C. Maximize the Intersections

C. Maximize the Intersections

作者:互联网

C. Maximize the Intersections

[link](Problem - C - Codeforces)

题意

在一个圆上有2n个不同的点,具有以下性质:无论你如何选择3条连接3个互不相干的点的弦,在圆内没有一个点严格属于所有3条弦。这些点按顺时针顺序被编号为1,2,…,2n。

最初,k条和弦连接了k对点,其方式是这些和弦的所有2k个端点是不同的。

你想画出n-k条额外的和弦,连接剩余的2(n-k)个点(每个点必须正好是一个和弦的端点)。

最后,让x成为所有n条弦的交叉点的总数。计算如果你以最佳方式选择n-k条弦,x能达到的最大值。

请注意,2n个点的确切位置并不重要,只要第一段中所述的属性成立即可。

题解

首先对于两条弦是否相交如何判断?

假设x1 < y1, x2 < y2且x1 < x2则当且仅当 x2 < y1 && y1 < y2时两弦有交点

什么情况下交点数最多?

假设有2n个点,从 1 - n + 1连一条边,这个弦的两侧的点数相同,弦的左右的点两两配对,则其余点对于该弦的贡献就是n - 1,因此,我们将所有的点按照 i - i + n 这种形式排列好,那么每一条弦的贡献一定都是n - 1,因为一共2n个点,n个弦,每个弦最多贡献是n - 1所以这种情况一定是最优的,因此,把剩下的没连过的点按照相对顺序依照这种方法连接即可。然后暴力跑一遍一否成立即可。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <unordered_map>
#include <cmath> 
#include <stack>
#include <iomanip> 
#define x first
#define y second
#define eps 1e-7
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const int N = 5e4 + 10, M = 30010, INF = 0x3f3f3f3f, P = 131, mod = 1e9 + 7;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int n, m;

bool check(PII c, PII d) { // 判断是否有交点 
	if (c.x > d.x) swap(c, d); // c靠前 
	return c.y < d.y &&  d.x < c.y;
}
int main () {
	cin.tie(nullptr)->sync_with_stdio(false);
	int T;
	cin >> T;
	while (T --) {
			cin >> n >> m; // n条弦和用了m条 
			vector<PII> chords; // 存所有弦的xi,yi 
			vector<bool> used(2 * n + 1, false); // 判断哪些弦题目中给了 
			for (int i = 1; i <= m; i ++ ) {
				int x, y;
				cin >> x >> y;
				if (x > y) swap(x, y); // 从小到大 定序 方便后面操作 
				chords.push_back({x, y});  // 将弦加入 
				used[x] = used[y] = true; // 表示用过了 
			}
			vector<int> unused; // 存没用过的弦 
			for (int i = 1; i <= 2 * n; i ++ )
				if (!used[i]) unused.push_back(i); // 找到所有没用过的弦 
			for (int i = 0; i < n - m; i ++ )  // 将所有没用过的弦按照相对顺序,依照最优策略连弦 
				chords.push_back({unused[i], unused[i + n - m]}); // 加入到方案内 
			int res = 0;
			for (int i = 0; i < n; i ++ )  // 暴力枚举 
				for (int j = i + 1; j < n; j ++ )
					res += check(chords[i], chords[j]); // 是否合理 
			cout << res << endl;
		}
	 return 0;
}



标签:typedef,Intersections,个点,int,long,Maximize,2n,include
来源: https://blog.csdn.net/a12377978/article/details/119105605