首页 > 其他分享 >GYM105139C Lili Likes Polygons

GYM105139C Lili Likes Polygons

时间:2024-07-28 11:56:07浏览次数:16  
标签:head int 割线 Lili tot GYM105139C 凹点 枚举 Polygons

记矩形的并为 \(P\),定义多边形的大小为它的顶点个数 \(|P|\),其 \(90\)°的顶角为凸角,\(270\)°的顶角为凹角并记凹点构成的集合为 \(C\),称竖直或水平在多边形内部分割开矩形的线为割线,连接了两个凹点的割线为好割线

贪心可以发现对于 \(P\) 的任意极小矩阵划分,所有的割线至少有一端是 \(P\) 上的凹点,即存在一个端点 \(\in C\),否则一定可以合并此割线两边的矩形

对于任意一个 \(P\) 的极小矩形剖分 \(R\) 及关于 \(R\) 的不相交的好割线集合 \(N\) 有 \(4|R|=|P|+2|C|-4|N|\),考虑利用内角和的变化证明,它原本的内角和等于 \(90\)°\(\times\) 凸点数\(+270\)°\(\times\) 凹点数\(=(|P|+2|C|)\times 90\)°,对于每一条 \(N\) 中的好割线将每个端点切为 \(90\)°与 \(180\)°两部分,前者构成最终矩阵的内角后者构成一条边,那么增量为 \(-2 \times 180\)°,对于不在 \(N\) 中的割线 \(a=(x,y)\),若 \(x\in C \wedge y \notin C\),那么它会将一条边或割线分为两个角从而与 \(x\) 带来的负增量抵消,否则 \(y\) 一定被其它割线分割从而与 \(y \notin C\) 的情况相同

考虑最大化 \(|N|\),由于只有竖直与水平的割线会相交,将竖直的好割线看作二分图左部点,水平的看作右部点,它们的交点看作它们之间的连边,那么所求转化为此图的最大独立集,使用网络流求解即可,考虑求解 \(|P|\) 与 \(|C|\),可以枚举每个四连通块,若只有一个点被覆盖则 \(|P| \leftarrow |P|+1\),至于两个多边形的一角重合的情况与 \(|C|\),钦定四联通块的右上角没有被覆盖并枚举其四个方向的被覆盖情况即可,考虑如何建图,将矩形离散化后可以使用二维数组模拟,找出所有凹点坐标后可以 \(\text{O}(|P|^2)\) 枚举并 \(\text{O}(k)\) 延展枚举另一个端点,由于每个凹点最多属于一个水平与竖直割线,所以均摊复杂度正确,再枚举它们是否相交即可

#include<bits/stdc++.h>
using namespace std;
int k,h,w,s,t,n,m,ans,val,tot=1,flow,l[301],p[301],r[301],q[301],d[701][701],c[701][701],head[8001],now[8001],dep[8001],nex[800001],edge[800001],ver[800001];
basic_string <int> vx,vy;
basic_string <tuple<int,int,int,int>> ux,uy;
void add(int u,int v,int w){
	ver[++tot]=v,edge[tot]=w,nex[tot]=head[u],head[u]=tot;
	ver[++tot]=u,edge[tot]=0,nex[tot]=head[v],head[v]=tot;
}
int bfs(){
	queue <int> q;
	for(int i=s;i<=t;i++) dep[i]=0,now[i]=head[i];
	dep[s]=1,q.push(s);
	while(q.size()){
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=nex[i]){
			if(edge[i]&&!dep[ver[i]]){
				dep[ver[i]]=dep[x]+1;
				q.push(ver[i]);
				if(ver[i]==t) return 1;
			}
		}
	}
	return 0;
}
int dinic(int x,int flow){
	if(x==t) return flow;
	int rest=flow,k=0;
	for(int i=now[x];i&&rest;i=nex[i]){
		now[x]=i;
		if(edge[i]&&dep[ver[i]]==dep[x]+1){
			k=dinic(ver[i],min(edge[i],rest));
			if(!k) dep[ver[i]]=0;
			rest-=k;
			edge[i]-=k;
			edge[i^1]+=k;
		}
	}
	return flow-rest;
}
int main(){
	scanf("%d",&k);
	for(int i=1;i<=k;i++) scanf("%d%d%d%d",&l[i],&p[i],&r[i],&q[i]),vx+=l[i],vx+=++r[i],vy+=p[i],vy+=++q[i];
	sort(begin(vx),end(vx)),vx.erase(unique(begin(vx),end(vx)),end(vx)),h=vx.size();
	sort(begin(vy),end(vy)),vy.erase(unique(begin(vy),end(vy)),end(vy)),w=vy.size();
	for(int i=1;i<=k;i++){
		l[i]=lower_bound(vx.begin(),vx.end(),l[i])-vx.begin()+1;
		r[i]=lower_bound(vx.begin(),vx.end(),r[i])-vx.begin()+1;
		p[i]=lower_bound(vy.begin(),vy.end(),p[i])-vy.begin()+1;
		q[i]=lower_bound(vy.begin(),vy.end(),q[i])-vy.begin()+1;
		d[l[i]][p[i]]++,d[l[i]][q[i]]--,d[r[i]][p[i]]--,d[r[i]][q[i]]++;
	}
	for(int i=1;i<=h;i++) for(int j=1;j<=w;j++) d[i][j]+=d[i-1][j]+d[i][j-1]-d[i-1][j-1];
	for(int i=1;i<=h;i++) for(int j=1;j<=w;j++) d[i][j]=d[i][j]>0;
	for(int i=1;i<=h;i++){
		for(int j=1;j<=w;j++){
			int cnt=d[i][j]+d[i-1][j]+d[i][j-1]+d[i-1][j-1];
			if(cnt==3) c[i][j]=1;
			if(cnt==1) ans++;
			if(!d[i][j]&&d[i-1][j]&&d[i][j-1]) ans++;
			if(!d[i][j]&&d[i+1][j]&&d[i][j-1]) ans++;
			if(!d[i][j]&&d[i-1][j]&&d[i][j+1]) ans++;
			if(!d[i][j]&&d[i+1][j]&&d[i][j+1]) ans++;
			if(!d[i][j]&&d[i-1][j]&&d[i][j-1]&&d[i-1][j-1]) ans+=2;
			if(!d[i][j]&&d[i-1][j]&&d[i][j+1]&&d[i-1][j+1]) ans+=2;
			if(!d[i][j]&&d[i+1][j]&&d[i][j-1]&&d[i+1][j-1]) ans+=2;
			if(!d[i][j]&&d[i+1][j]&&d[i][j+1]&&d[i+1][j+1]) ans+=2;
		}
	}
	for(int i=1;i<=h;i++){
		for(int j=1;j<=w;j++){
			if(c[i][j]){
				if(d[i-1][j]&&d[i][j]){
					int k=j;
					while(d[i-1][k]&&d[i][k]) k++;
					if(c[i][k]) ux+={i,i,j,k};
				}
				if(d[i][j-1]&&d[i][j]){
					int k=i;
					while(d[k][j-1]&&d[k][j]) k++;
					if(c[k][j]) uy+={i,k,j,j};
				}
			}
		}
	}
	n=ux.size(),m=uy.size(),val=n+m,t=n+m+1;
	for(int i=1;i<=n;i++) add(s,i,1);
	for(int i=1;i<=m;i++) add(i+n,t,1);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			auto [a,b,c,d]=ux[i-1];
			auto [e,f,g,h]=uy[j-1];
			if(e<=a&&a<=f&&c<=g&&g<=d) add(i,j+n,1); 
		}
	}
	while(bfs()) while(flow=dinic(s,1e9)) val-=flow;
	printf("%d",(ans-val*4)/4);
	return 0;
}

标签:head,int,割线,Lili,tot,GYM105139C,凹点,枚举,Polygons
From: https://www.cnblogs.com/zyxawa/p/18328063

相关文章

  • kalilinux的200个命令
      pwd-显示当前工作目录的路径ls-列出目录内容cd-更改目录echo-显示文本cat-连接文件并显示touch-创建文件rm-删除文件或目录mv-移动或重命名文件或目录cp-复制文件或目录chmod-更改文件或目录的权限chown-更改文件或目录的所有者grep-......
  • [992] Remove holes within polygons in a shapefile
    Toremoveholeswithinpolygonsinashapefile,youcanusethegeopandaslibraryinPython.Here'showyoucandoit:importgeopandasasgpd#Readtheshapefilegdf=gpd.read_file('path_to_shapefile.shp')#Removeholeswithinpolygon......
  • [ABC211F] Rectilinear Polygons 题解
    [ABC211F]RectilinearPolygons题解思路什么的上一篇题解已经写的非常明白了,这里只是提供一个补充&另一个实现的方法。思路解析先说结论:扫描线。顾名思义,扫描线的本质就是用一条线沿着\(x\)或\(y\)轴扫过去,每碰到一条边就记录一下加边后是面积是增加还是减少,然后用树状......
  • ꧁ ENDER LILIES ꧂
    "我有对每一部优秀作品写观后感的习惯."1她在白教区的一隅醒来.我们称呼她为莉莉吧.没有形体的黑骑士守护着她.在她遇到危险时会现身,据说是来自一个古老契约.教区残破不堪,充满危险.她越过地面上虫子一样的秽鬼.教区中有一个与其他秽鬼完全不同的人类.只不过这个人......
  • ArcMap中Cut Polygons Tool工具将一个面图层切割为多个部分
      本文介绍在ArcGIS下属ArcMap软件中,通过“CutPolygonsTool”工具,对一个面要素矢量图层加以手动分割,从而将其划分为指定形状的多个部分的方法。  对于一个面要素矢量文件,有时我们需要对其加以划分,通过手动勾勒新的线条的方式,将其中原本的一个面分割为多个指定的小区域;本文就......
  • AT_abc251_g Intersection of Polygons Solution
    AT_abc251_gIntersectionofPolygonsSolutionPreface由于某些\(\LaTeX\)的原因,本文的公式无法正常查看,建议读者访问博客以获得正常阅读体验。Statement逆时针地给定一个有\(N\)个顶点,第\(i\)个顶点为\((x_i,y_i)\)的凸包\(P_0\)。再给出\(M\)个向量\((u_i,v......
  • AtCoder Beginner Contest 251 G Intersection of Polygons
    洛谷传送门AtCoder传送门经典结论,一个点\(P(x,y)\)在一个凸多边形内部\(S=\{(x_i,y_i)\}\)的充要条件是\(\foralli\in[1,n],(x_{i+1}-x_i,y_{i+1}-y_i)\times(x-x_i,y-y_i)\ge0\),其中\(S\)的点按照逆时针排列。然后我们运用叉积的一个性质......
  • KaliLinux安装Burpsuite
    注意事项1.注意linux位数安装jdk之前先输出uname-a,看看kalilinux是32位的还是64位,例如此处我的kali是32位的,因此需下载的是32位的jdk2.jdk版本jdk版本最好是oracle的,若使用的是openjdk很可能会出现burpsuite闪退现象安装JDK1.解压jdk将jdk压缩包解压至kali的/opt目录......
  • lilishop 锁
    privatevoidsavePaymentLog(PayParampayParam){//同一个会员如果在不同的客户端使用预存款支付,会存在同时支付,无法保证预存款的正确性,所以对会员加锁......
  • Linux开启ssh并允许root登录(ubuntu、centos、kalilinux)
    1、Ubuntu开启ssh服务及允许root登录1)安装ssh服务器端Ubuntu默认没有安装ssh的server,需要安装apt-getinstallopenssh-serverssh客户端是默认安装的,连接其它ssh服......