彗星OJ - コンテスト#13-C2

彗星OJ - コンテスト#13-C2

C2-ロイヤル仏石の鉢 - 「(難しい版) - 意志を壊れていません

それは互いに素-セットです。タイトルは最近、一見多くを見つけるの互いに素セットを行って。

考え

点0 1からのみ考慮各治療矩形に、最初の検討。コントロールの我々複雑\(O(nm)を\)

そこで、我々は、0の各点での位置を維持する方法を検討してください。私たちが知っているので互いに素セットは、いくつかの要素の同じ関係を維持するために使用されますしたがって、我々は、各点を検討し\(FA \)が行でゼロ位置です。そこで、我々は染め0 1点を入れたときに、この時点のポイントと左マージ。私たちは、この現在のポイント保証することができます\(FA \)は、独自の「息子」確保しながら、次の位置0です\(FA \)をゼロに次の新しい場所に。

それでは、どのように動的なメンテナンスUnicom社のブロックを検討してください。

リンクブロックのメンテナンスやチェックのセットを開きます。我々は、すべての答え1プラス1を与えてみましょう。ときに、2つのブロック1ユニコム回答減算1を組み合わせます。

ユニコムシーケンス、プロセス1は、マージ組み合わせ周囲みなすことができるたびに制御しません。(これは、すべて入れ互いに素-セットのもう一つの重要なキャラクター。ある関係を得ることができます戻ってすべての関係を取得することができ、最終的に組み合わされて)。

複雑\(O(NM \アルファ(NM)+ NQ)\) (プラス合併ランク別)

コード

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1005;
int map[maxn][maxn],fa1[maxn][maxn],fa2[maxn*maxn],id[maxn][maxn],n,m,q,tot,ans;
char s[maxn];
int get1(int x,int y) {return (fa1[x][y]==y)?y:fa1[x][y]=get1(x,fa1[x][y]);}
void uni1(int x,int u,int v){fa1[x][get1(x,u)]=get1(x,v);}
int get2(int x){return (fa2[x]==x)?x:fa2[x]=get2(fa2[x]);}
void uni2(int u,int v){fa2[get2(u)]=get2(v);}
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
void mark(int x,int y) {//color (x,y)
    id[x][y]=++tot;ans++;fa2[tot]=tot;
    if(get1(x,y)!=get1(x,y+1))uni1(x,y,y+1);
    for(int i=1;i<=4;i++) {
        int nx=x+dx[i],ny=y+dy[i];
        if(1<=nx<=n&&1<=ny<=m&&id[nx][ny]) {
            if(get2(id[nx][ny])!=get2(id[x][y])){uni2(id[nx][ny],id[x][y]);ans--;}
        }
    }
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%s",s+1);
        for(int j=1;j<=m;j++)map[i][j]=(s[j]=='1')?1:0;
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=m+1;j++)fa1[i][j]=j;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(map[i][j])mark(i,j);
    scanf("%d",&q);
    for(int t=1;t<=q;t++) {
        int d[5];scanf("%d%d%d%d",&d[1],&d[3],&d[2],&d[4]);//x1 x2 y1 y2
        for(int i=d[1];i<=d[2];i++) {
            for(int j=get1(i,d[3]);j<=d[4];j=get1(i,j)) {
                mark(i,j);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/GavinZheng/p/11746813.html