[CF1242E] Planar Perimeter[题解]

Planar Perimeter

题意

\(n\) 个多边形(不一定凸),要求第 \(i\) 个多边形有 \(a_i\) 条边,现在你要将多边形拼接起来变成一个大多边形,要求:

  • 多边形两两交集面积为零。

  • 每个多边形的边要么与另一个多边形的边重合,要么是大多边形的外围边。

求大多边形边数最小值,并构造一种方案(输出哪些顶点重合了)。

\(1\leq n\leq 10^5,\sum a_i \leq 3\times 10^5\)

分析

考虑将 \(a_i\) 降序排列,考虑最大的一个面 \(a_1\)。如果 \(a_1 - \sum_{i=2}^n(a_i - 2)\geq3\),则最终的边长即为 \(a_1 - \sum_{i=2}^n(a_i - 2)\),一个新加的面最多让周长减少 \(a_i - 2\),这是比较显然的。但我们不可能存在边数小于 \(3\) 的多边形,所以,在某个时刻我们也许不能再让多边形的边数减小,相反,我们甚至有可能使它增加,于是我们只要在构造到第 \(i\) 个面时满足 \(C \ge a_{i+1}\) 的条件下尽可能让周长变小,我们最后的答案就是 \(4 - (\sum_{i = 1}^n a_i)\) \(mod\) \(2\),具体的实现我们可以用双端队列维护当前外面的边。

还有最后一个问题,我们构造出的图形可能存在重边,具体地,即我们在多边形的一条边上同时添加了两个三角形,我们可以在每次加入多边形后右移一位,从下一条边开始添加,就能有效避免这个问题,正确性是显然的。

CODE

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
inline int read()
{
	int s = 0, w = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') { if(ch == '-') w *= -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
	return s * w;
}
struct node{ int v, id; };
int n, cnt;
inline bool cmp(node x, node y) { return x.v > y.v; }
vector<node> arr;
vector<int> vec[N];
int main()
{
	n = read();
	for(register int i = 0; i < n; i++){
		int x = read();
		arr.push_back((node){x, i});	
	}
	sort(arr.begin(), arr.end(), cmp);
	deque<int> q;
	for(register int i = 0; i < arr[0].v; i++){
		q.push_back(cnt), vec[arr[0].id].push_back(cnt);
		cnt++;
	}
	for(register int i = 1; i < n; i++){
		int x = arr[i].v, y = arr[i].id;
		int p = min(x - 1, ((int)q.size() + x - (i == n - 1 ? 3 : arr[i + 1].v)) / 2);
		for(register int j = 0; j < p - 1; j++)
			vec[y].push_back(q.back()), q.pop_back();
		vec[y].push_back(q.back());
		for(register int j = p; j < x - 1; j++)
			vec[y].push_back(cnt), q.push_back(cnt), cnt++;
		vec[y].push_back(q.front());
		q.push_back(q.front()), q.pop_front();
	}
	cout << cnt << "\n";
	for(register int i = 0; i < n; i++){
		for(register int j : vec[i])
			cout << j + 1 << " ";
		cout << "\n";
	}
	return 0;
}
posted @ 2022-02-13 11:57  ╰⋛⋋⊱๑落叶๑⊰⋌⋚╯  阅读(51)  评论(2编辑  收藏  举报