zoukankan      html  css  js  c++  java
  • 【JZOJ1404】菱形内的计数【并查集】

    题目:

    题目链接:https://jzoj.net/senior/#main/show/1404
    给出一个菱形,问这个菱形中有多少个内部不含边的平行四边形。


    思路:

    我们先把这个菱形转换为正方形。例如样例的转换方式如下:
    在这里插入图片描述
    那么接下来我们就是要求有多少个中间没有边的矩形。
    我们可以记录每一个矩形的大小和最右上方(x1,y1)(x1,y1)和最左下方的点(x2,y2)(x2,y2),这样就可以算出每一个矩形的面积。最后枚举每一个矩形,如果满足(x1x2)(y1y2)=s(x1-x2)(y1-y2)=s,那么这就是一个矩形。
    如何判断矩形中间有没有边?我们只要枚举每一条边,如果这一条边的两边在一个连通块内,那么就将这一个连通块标记一下即可。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=800010,M=900;
    int n,x,y,p1,p2,ans,father[N],MAXx[N],MINx[N],MAXy[N],MINy[N],size[N];
    char c,ch[M*2][M*2];
    //   92   /47
    
    int com(int x,int y)
    {
    	return (x-1)*n+y;
    }
    
    int find(int x)
    {
    	return x==father[x]?x:father[x]=find(father[x]);
    }
    
    void merge(int x,int y)
    {
    	x=find(x),y=find(y);
    	if (x==y) return;
    	MAXx[x]=max(MAXx[x],MAXx[y]);
    	MAXy[x]=max(MAXy[x],MAXy[y]);
    	MINx[x]=min(MINx[x],MINx[y]);
    	MINy[x]=min(MINy[x],MINy[y]);
    	size[x]+=size[y];
    	father[y]=x;
    }
    
    int main()
    {
    	scanf("%d
    ",&n);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    		{
    			int p=com(i,j);
    			father[p]=p; size[p]=1;
    			MAXx[p]=i+1; MINx[p]=i;
    			MAXy[p]=j+1; MINy[p]=j;
    		}
    	for (int i=1;i<=n*2;i++)
    	{
    		int j=0;
    		while (c=getchar())
    		{
    			if (c=='
    ') break;
    			ch[i][++j]=c;
    		}
    	}
    	for (int i=1;i<=n;i++)
    		for (int j=2;j<=n;j++)
    		{
    			x=i+j-1; y=n+1-i+j-1;
    			if (ch[x][y]==' ') merge(com(i,j),com(i,j-1));
    		}
    	for (int i=1;i<=n;i++)
    		for (int j=2;j<=n;j++)
    		{
    			x=i+j-1; y=n+2*i-x;
    			if (ch[x][y]==' ') merge(com(j,i),com(j-1,i));
    		}
    	for (int i=1;i<=n;i++)
    		for (int j=2;j<=n;j++)
    		{
    			x=i+j-1; y=n+1-i+j-1;
    			if (ch[x][y]!=' ' && find(com(i,j))==find(com(i,j-1)))
    				size[find(com(i,j))]=-233;
    		}
    	for (int i=1;i<=n;i++)
    		for (int j=2;j<=n;j++)
    		{
    			x=i+j-1; y=n+2*i-x;
    			if (ch[x][y]!=' ' && find(com(j,i))==find(com(j-1,i)))
    				size[find(com(j,i))]=-233;
    		}
    	for (int i=1;i<=n*n;i++)
    		if (father[i]==i && size[i]==(MAXx[i]-MINx[i])*(MAXy[i]-MINy[i]))
    			ans++;
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    【leetcode】Valid Palindrome
    【leetcode】Longest Common Prefix
    【leetcode】Intersection of Two Linked Lists
    【leetcode】Compare Version Numbers
    【leetcode】Pascal's Triangle
    ubuntu 14.04下spark简易安装
    【leetcode】Number of 1 Bits
    【leetcode】LRU Cache
    【leetcode】Container With Most Water
    【leetcode】Roman to Integer
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11997993.html
Copyright © 2011-2022 走看看