zoukankan      html  css  js  c++  java
  • atcoder 131 F

    题目链接

    F - Must Be Rectangular!

    Time Limit: 2 sec / Memory Limit: 1024 MB

    Score :
    600
    points

    Problem Statement

    There are
    N
    dots in a two-dimensional plane. The coordinates of the i-th dot are ((x_i,y_i)).

    We will repeat the following operation as long as possible:

    Choose four integers a, b, c, d (a

    c
    ,
    b

    d
    )
    such that there are dots at exactly three of the positions
    (
    a
    ,
    b
    )
    ,
    (
    a
    ,
    d
    )
    ,
    (
    c
    ,
    b
    )
    and
    (
    c
    ,
    d
    )
    , and add a dot at the remaining position.

    We can prove that we can only do this operation a finite number of times. Find the maximum number of times we can do the operation.

    Constraints

    • 1≤N≤(10^5)

    ....

    详见题目链接

    思路

    将每一个点拆成两个点即横纵各一点

    然后将该两点连线

    好处

    自然将横坐标相等或纵坐标相等的若干点构成一个联通块

    是由(0,1),(1,1),(1,2),(1,0),(2,2)通过以上方法构成的

    统一将纵坐标加上一个10的目的是避免x,y不能相互区分

    然后 这样做了有什么用吗?

    答案是肯定的

    用并查集来维护

    for(i = 1;i <= n;i++)
    	{
    		int u,v;
          //u-x,v-y
    		scanf("%d%d",&u,&v);
    		f[FindSet(u)] = FindSet(v + MAXN);
    	}
    
    

    再设数组difx[]dify[]

    dif即difference用来统计横坐标或纵坐标的不同数的多少

    因为单纯点数 可能在行或列上有重合

    for(i = 1;i <= MAXN;i++)
    	difx[FindSet(i)]++;
    for(i = MAXN + 1;i <= MAXN * 2;i++)
    	dify[FindSet(i)]++;
    
    

    1(0,1)

    2(1,1)

    3(1,0)

    4(1,2)

    5(2,2)

    如图 的话 横坐标或纵坐标的不同数的多少各为3

    乘起来为整个矩阵点数 再减去已有的 就是答案

    但考虑到 可能不止一个联通块 所以需要一个枚举的操作

    for(i = 1;i <= MAXN * 2;i++)
    	ans += 1ll * difx[i] * dify[i];
    

    但聪明的同学可能会想到

    如果那些构不成(横或纵相等的在3个以下)的被误算了怎么办

    for(i = 1;i <= MAXN;i++)
    	difx[FindSet(i)]++;
    for(i = MAXN + 1;i <= MAXN * 2;i++)
    	dify[FindSet(i)]++;
    
    

    先前的代码 是加在祖先上的

    如果只有一个点(该点所在的行和列无它点)第一个FindSet(i) = 该点的纵坐标加MAXN

    可见只加了1 和 后面的减n是抵消了的

    然后 又会有同学提到 并查集的初始化

    	for(i = 1;i <= MAXN * 2;i++) f[i] = i;
    
    

    公平地给所有赋了值 包括一些实际上不存在的点

    那么是否有可能再次造成误算呢?

    这位同学 您又错了

    因为对于一个不存在的i
    difx[FindSet(i)]++;即difx[i]++;

    而ans加时加的是difx[FindSet(i)]*dify[FindSet(i)]

    细节

    difx的i和dify的i是错开枚举的

    即difx[i]>0定有dify[i]

    反之亦然

    所以不会干扰结果

    代码

    #include <cstdio>
    #include <vector>
    #include <algorithm>
     
    using namespace std;
    
    const int MAXN = 100000,MAX = 200005;
    int f[MAX],difx[MAX],dify[MAX];
    inline int FindSet(int a)
    {
    	if(a == f[a]) return a;
    	return f[a] = FindSet(f[a]);
    }
    int main()
    {
        int i,n; 
    	scanf("%d",&n);
    	for(i = 1;i <= MAXN * 2;i++) f[i] = i;
    	for(i = 1;i <= n;i++)
    	{
    		int u,v;
    		scanf("%d%d",&u,&v);
    		f[FindSet(u)] = FindSet(v + MAXN);
           //不能写成f[FindSet(u)] = v + MAXN;
           //否则会RE我也不知道为什么QAQ
    	}
    	for(i = 1;i <= MAXN;i++)
    		difx[FindSet(i)]++;
    	for(i = MAXN + 1;i <= MAXN * 2;i++)
    		dify[FindSet(i)]++;
    	long long ans = 0;
    	for(i = 1;i <= MAXN * 2;i++)
    		ans += 1ll * difx[i] * dify[i];
    	printf("%lld",ans - n);
        return 0;
    }
    
  • 相关阅读:
    HTC(G13)野火A510e获取root权限详细图文教程
    aliyun的linux服务器配置
    js判断是否为数字, 是否为整数, 是否为浮点数
    帝国cms管理员帐号、登陆密码、登陆认证码、登陆安全答案忘记了怎么办?
    帝国cms后台登陆出现空白页的问题所在及解决方法
    jQuery1.4.2与json格式兼容问题
    [IoC容器Unity]第四回:使用范例
    [IoC容器Unity]第二回:Lifetime Managers生命周期
    [Scheduled Timer]第八回:总结
    [设计模式原则]第五回:迪米特原则
  • 原文地址:https://www.cnblogs.com/resftlmuttmotw/p/11323198.html
Copyright © 2011-2022 走看看