CodeForces 1242E Planar Perimeter

时间:2020-05-28
本文章向大家介绍CodeForces 1242E Planar Perimeter,主要包括CodeForces 1242E Planar Perimeter使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

CodeForces 1242E Planar Perimeter

https://codeforces.com/contest/1242/problem/E

求这样的一个平面图,满足

  1. 存在 \(f\) 个面,第 \(i\) 个面为 \(a_i\) 边形
  2. 直径最小
  3. 无重边,自环

输出方案,一个数 \(n\) 表示点数,然后对于对于每个面输出 \(u_1,u_2,\cdots,u_{a_i}\) 表示图中存在这样的一个环.

\(1 \le f \le 10^5, 3 \le a_i \le 3 \times 10^5, \sum a_i \le 3 \times 10^5\)

Tutorial

可以通过操作将一个直径为 \(n\) 的平面图和一个 \(a_i\) 边形glue,且可以选择glue \(r\) 条边,这样之后得到一个直径为 \(n+a_i-2r\) 的平面图.

void glue(int x,int r,int m)
{
	for(int i=1;i<r;++i)
	{
		an[x].push_back(q[--tl]);
	}
	an[x].push_back(q[tl-1]);
	for(int i=r+1;i<m;++i)
	{
		an[x].push_back(q[tl++]=++n);
	}
	an[x].push_back(q[tl++]=q[hd++]);
}
// an[x]表示第x个多边形的环
// q[hd...tl]表示平面图当前的直径
// 第12行的目的为保证无重边

现在考虑如何选择 \(r\) .

首先将所有面按照 \(a_i\) 降序排列,然后将 \(i=2,3,\cdots,f\) 依次和 \(a_1\) 合并,且要让 \(r\) 在保证最后直径至少为 \(3\) 的情况下尽量大.为方便设 \(a_{n+1}=3\) ,则每次的 \(r=\min\{a_i-1,\lfloor \dfrac {(tl-hd+a_i-a_{i+1})}2 \rfloor\}\) ,第一项的目的是最大化 \(r\) ,第二项的目的是保证最后的直径至少为 \(3\)

Code

https://codeforces.com/contest/1242/submission/65031118

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
inline char nc()
{
//	return getchar();
	static char buf[100000],*l=buf,*r=buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x)
{
	x=0; int f=1,ch=nc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
	x*=f; 
}
const int maxf=1e5+50;
const int maxn=3e5+50;
const int maxnode=maxn+maxf;
int f;
int n;
int hd;
int tl;
int q[maxnode];
vector<int> an[maxf];
struct node
{
	int x,id;
	inline bool operator <(const node &other) const
	{
		return x>other.x;
	}
} a[maxf];
void glue(int x,int r,int m)
{
	for(int i=1;i<r;++i)
	{
		an[x].push_back(q[--tl]);
	}
	an[x].push_back(q[tl-1]);
	for(int i=r+1;i<m;++i)
	{
		an[x].push_back(q[tl++]=++n);
	}
	an[x].push_back(q[tl++]=q[hd++]);
}
int main()
{
	read(f);
	for(int i=1;i<=f;++i)
	{
		read(a[i].x),a[i].id=i;
	}
	sort(a+1,a+f+1);
	for(int i=1;i<=a[1].x;++i)
	{
		q[tl++]=++n;
		an[a[1].id].push_back(n);
	}
	a[f+1].x=3;
	for(int i=2;i<=f;++i)
	{
		int m=a[i].x;
		int r=min(m-1,(tl-hd+m-a[i+1].x)/2);
		glue(a[i].id,r,m);
	}
	printf("%d\n",n);
	for(int i=1;i<=f;++i)
	{
		for(int j=0;j<an[i].size();++j)
		{
			if(j) printf(" ");
			printf("%d",an[i][j]);
		}
		printf("\n");
	}
	return 0;
}

原文地址:https://www.cnblogs.com/ljzalc1022/p/12968304.html