其他分享
首页 > 其他分享> > 平面二维点对问题(转化一维)

平面二维点对问题(转化一维)

作者:互联网

【元素周期表】通过观察点对构造规律,转化成矛盾或者传递关系

平面坐标系内,给出p个点对(x,y),如果有3个同行或者同列的点对,那么他们组成的“矩形四个角”就都被覆盖,求最少添加多少点使得所有n*m区域都被覆盖。

部分分:p=0,考虑构造,发现只要靠边一行一列都填满就可以满足要求
正解:把横坐标看成一边的点对,纵坐标看成一边点对,如果(x,y)存在点,就连接x<-->y。发现对于矩形3点构成补成的1个点对连通性没影响,所以相当于求添加多少边使得所有1n和1m联通。ans=联通块数量-1

点击查看代码






#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<deque>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define rint register int
#define _f(i,a,b) for(rint i=a;i<=b;++i)
#define f_(i,a,b) for(rint i=a;i>=b;--i)
#define chu printf
#define ll long long
#define INF 2147483647
inline ll re()
{
	ll h=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')h=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*h;
}
struct node
{
	int to,nxt;
}e[400000+100];
int head[400000+100],tot,vis[400000+10],ans;
inline void Add(int u,int v)
{
	e[++tot].to=v;e[tot].nxt=head[u];head[u]=tot;
}
int n,m,q;
inline void dfs(int x)
{
	vis[x]=1;
	for(rint i=head[x];i;i=e[i].nxt)
	{
		int to=e[i].to;
		if(vis[to])continue;
		dfs(to);
	}
}
int main()
{
	//freopen("","r",stdin);
	//freopen("","w",stdout);
	n=re(),m=re(),q=re();
	_f(i,1,q)
	{
		int r=re(),c=re();Add(r,c+n);Add(c+n,r);
	}
	_f(i,1,n+m)
	if(!vis[i])++ans,dfs(i);
	chu("%d",ans-1);
	return 0;
}
/*
*/

【线段树区间操作】数据结构维护连续区间点对。质数合数修改分别维护。

【完美子图-馈赠3】a[x]=y,转换成求a的连续数值子串数量,用线段树+单调队列从左向右扫描累计\(Max[S]-Min[S]=R-L\)的区间个数

标签:ch,rint,ll,getchar,二维,一维,平面,include,define
来源: https://www.cnblogs.com/403caorong/p/16674041.html