[BZOJ4668]冷戦(互いに素セット)

説明
1946鮎3 3月5日、元英国首相ウィンストン・チャーチルは、正式に冷戦への前奏曲を開いた、米国フルトンで「鉄のカーテンのスピーチ」を発表しました。世界では「超大国」として米国とソ連との、二国とその同盟国との間に世界の覇権を争うためには、数十年のための闘争を開始しました。この期間中、深刻な相違や葛藤が、両側は通常、ローカルプロキシ戦争、科学技術と軍拡競争、宇宙開発競争、外交競争を通じて戦う大規模な世界的な戦争(第二次世界大戦III)勃発を回避しようとしているが、いわゆる「冷たい」「相互封じ込めは、力を移動していない」という方法で、「冷たい戦争。」
Reddingtonは、米国の提督です。なぜなら、戦争の状況を非常に緊張しているので、彼はトラブルに自分の国を避けるために、ソ連の様々な活動を見て時間を必要とします。Nの軍事工場と、しかしため、不適切な計画の世界ではソ連に、これらの軍事工場間の鉄道の不在で始まる、より高速な武器を製造するために、ソ連が道路の数を建設することを決めたいくつかの軍事工場ユニコムます。
Reddingtonは、ソ連のスケジュールを構築してきた、と彼は軍事工場2ユニコム、だけでなく、道路の建設の最初のどのかどうかユニコムに常に注意を払う必要があります。具体的には、今、M操作の合計があり、操作は2つのカテゴリに分類されます。
•0 UVは、この操作は鉄道の接続は、注意鉄道が双方向である軍事工場のuとv数ソ連軍の工場数の建設になります。
•1 UV、Reddington uはV番早い鉄道の新しいセクションを追加した後に中国聯通、出力0の動作にいくつか、そうでない場合にリンクする軍事工場や軍事工場の数を知る必要があり、
最強の米国の科学者として、Reddingtonはあなたの助けの設計を必要とします彼の要求を満たすことができますプログラム。
入力
最初の行二つの整数N、M。
次のM行、各挙動0 UVまたは1つのUVの形態。
データは、各側のために、暗号化されたプラスまたは本当のuを依頼され、Vは、お問い合わせへの最後の答えにVのXOR Uを読みに等しいです。開始値は0です。
1≤N、M≤500000、 Uは復号化、V満たす1≤U、V≤N、 UはVに等しくない
出力
場合、そのエッジ意志ユニコムの添加後にV最早、各動作のために、出力uとこの操作はユニコム、0が出力されません。
入力サンプル
5 9
0 1 4
。1 5 2
0 2 4
0 4。3
。1 3 1
0 7 0
0 6 1
0 6 1
1つの2 6
サンプル出力
0
。3
。5

ほとんどの人が互いに素セットを考えることができるはず、「中国聯通」の単語を参照してください。

あなたは、鉄道の記録数が、このコレクションとチェックし、それが全体の互いに素セット、それを軽減する方法のその時の複雑さを横断しなければならないにして収集し、同時にチェックできるように、側面に参加する最初のを見て?

私たちは、操作がしたらことを確認することができますように、ランクによってマージも\(O(logN個)\) それはパス圧縮ではありません)、私たちは、最初のいくつかの鉄道を建設されたレコードを同じ時間をマージすることができます。

それでは、どのクエリを実行しますか?

最後の操作であることを確認するために\(O(LOGN)\)あなたはLCAアップ2点のジャンプからの暴力を指示することができますので、最初のポイントは、ルート、パスマークマーク、イベントまでジャンプアップで第二の点をジャンプすることがあります道路に沿って構築された最大の鉄道を記録し、マーキングのポイントに、最後はクリア覚えています。

#include<bits/stdc++.h>
#define N 500010
using namespace std;
struct data
{
    int fa,deep,id;
}a[N];
int n,m,op,x,y,cnt,lastans;
bool vis[N];
int getfa(int x)
{
    while(a[x].fa!=x)
    {
        x=a[x].fa;
    }
    return x;
}
int query(int x,int y)
{
    int x2=x,y2=y,ans=0;
    while(a[x2].fa!=x2)//一号点先跳
    {
        vis[x2]=1;
        x2=a[x2].fa;
    }
    vis[x2]=1;
    while(!vis[y2]&&a[y2].fa!=y2)//跳二号点
    {
        y2=a[y2].fa;
    }
    x2=x;
    if(!vis[y2])//无交点
    {
        while(a[x2].fa!=x2)
        {
            vis[x2]=0;
            x2=a[x2].fa;
        }
        vis[x2]=0;
        return 0;
    }
    while(a[x2].fa!=x2)
    {
        vis[x2]=0;
        x2=a[x2].fa;
    }
    vis[x2]=0;//y2是lca
    while(x!=y2)//统计答案
    {
        ans=max(ans,a[x].id);
        x=a[x].fa;
    }
    while(y!=y2)
    {
        ans=max(ans,a[y].id);
        y=a[y].fa;
    }
    return ans;
}
int main()
{
//  freopen("1.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++)
    {
        a[i].fa=i;
        a[i].deep=1;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&op,&x,&y);
        x^=lastans;
        y^=lastans;
        if(op==0)
        {
            int xx=getfa(x),yy=getfa(y);
            cnt++;
            if(a[xx].fa!=a[yy].fa)
            {
                if(a[xx].deep>a[yy].deep)
                {
                    swap(xx,yy);
                }
                a[xx].fa=yy;
                a[xx].id=cnt;
                if(a[xx].deep==a[yy].deep)
                {
                    a[yy].deep++;
                }
            }
        }else{
            printf("%d\n",lastans=query(x,y));
        }
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/2017gdgzoi44/p/11850907.html