矩形填補

矩形填補


問題描述

給定平面 n 個黑點,如果平面一個邊平行於座標軸的矩形 3 個角是黑色的那麼就把那個矩形的第 4 個角改成黑色,最後平面上將會有多少個黑點


輸入格式

第一行一個整數 n (30% 的數據 n<=100100% 的數據 n<=2105 ),表示最初有 n 個點接下來 n 行,每行兩個整數 xi ,yi (絕對值<=109 ),表示第 i 個點的座標


輸出格式

一個整數,表示最後有多少個點


輸入1

3
1 1
1 2
2 2


輸出1

4


輸入2

5
0 0
1 0
0 1
1 2
2 1


輸出2

9


Solution

首先我們把縱座標相同的點合併成一條線。
注意到,有橫座標相同的點的兩條線或矩形 可構成的最大矩形中的每個點都可以被染色。
所以,我們把 有橫座標相同的點的兩條線或矩形 能構成的最大矩形的邊長求出來,然後逐個考慮即可。


Code

#include <iostream>
#include <cstdio>
#include <algorithm>

#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))

#define LL long long

using namespace std;

LL n,ans,tt[200010],h[200010],fa[200010],xx[200010],yy[200010];
bool vis[200010];

struct P{LL x,y,z;}p[200010];

LL find(LL x){
    LL tmp=x,pre;
    while(tmp!=fa[tmp])tmp=fa[tmp];
    while(x!=tmp)pre=fa[x],fa[x]=tmp,x=pre;
    return tmp;
}

void merge(LL x,LL y){
    LL fx=find(x),fy=find(y);
    if(fx==fy){
        tt[fx]--;
        return;
    }
    fa[fy]=fx;
    if(yy[fx]==yy[fy])tt[fx]+=tt[fy];
    else{
        h[fx]+=h[fy];
        tt[fx]+=tt[fy]-1;
    }
}

bool cmp1(P x,P y){
    return ((x.y<y.y)||(x.y==y.y&&x.x<y.x));
}

bool cmp2(P x,P y){
    return ((x.x<y.x)||(x.x==y.x&&x.y<y.y));
}

inline void in(LL &x){
    x=0;char ch=getchar();LL flag=1;
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-'){flag=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    x*=flag;
}

int main(){

    freopen("filling.in","r",stdin);
#ifndef DEBUG
    freopen("filling.out","w",stdout);
#endif

    in(n);
    for(LL i=1;i<=n;i++)in(p[i].x),in(p[i].y),p[i].z=i,xx[i]=p[i].x,yy[i]=p[i].y,fa[i]=i,h[i]=1,tt[i]=1;
    sort(p+1,p+n+1,cmp1);
    for(LL i=1,it;i<=n;i=it){
        LL pre=p[i].y;it=i+1;
        while(p[it].y==pre&&it<=n){
            merge(p[i].z,p[it].z);
            it++;
        }
    }
    sort(p+1,p+n+1,cmp2);
    for(LL i=1,it;i<=n;i=it){
        LL pre=p[i].x;it=i+1;
        while(p[it].x==pre&&it<=n){
            merge(p[i].z,p[it].z);
            it++;
        }
    }
    for(LL i=1;i<=n;i++){
        LL x=find(i);
        if(vis[x])continue;
        vis[x]=true;
        ans+=tt[x]*h[x];
    }
    printf("%lld\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章