【BZOJ2733】永無鄉(線段樹,並查集)

【BZOJ2733】永無鄉(線段樹,並查集)

題面

BZOJphp

題解

線段樹合併ios

線段樹合併是一個頗有趣的姿式spa

前置技能:動態開點線段樹code

具體實現:每次合併兩棵線段樹的時候,假設叫作\(t1,t2\),其中要把\(t2\)合併進\(t1\)遞歸

假設當前位置\(t1\)沒有節點,則直接把\(t2\)的這個位置給\(t1\)(直接接上去就好啦)get

若是\(t2\)這個位置沒有節點,那麼直接\(return\)string

不然,兩個位置都有節點,把兩個節點的信息合併,而後遞歸合併左右子樹it

簡單的代碼以下:io

void MergeNode(int &r1,int r2)
{
    if(!r1){r1=r2;return;}
    if(!r2)return;
    t[r1].v+=t[r2].v;
    MergeNode(t[r1].ls,t[r2].ls);
    MergeNode(t[r1].rs,t[r2].rs);
}

回到這道題目class

對於每個聯通快維護一個值域線段樹

每次在線段樹上二分一下第\(K\)大就行了

每次修橋至關於合併兩棵線段樹

用並查集維護一下聯通快就能夠啦,多簡單

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 120000
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int n,m,Q;
struct Node
{
    int ls,rs;
    int v;
}t[MAX<<4];
int tot;
int a[MAX];
void Modify(int &x,int l,int r,int p)
{
    if(!x)x=++tot;t[x].v++;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(p<=mid)Modify(t[x].ls,l,mid,p);
    else Modify(t[x].rs,mid+1,r,p);
}
void MergeNode(int &r1,int r2)
{
    if(!r1){r1=r2;return;}
    if(!r2)return;
    t[r1].v+=t[r2].v;
    MergeNode(t[r1].ls,t[r2].ls);
    MergeNode(t[r1].rs,t[r2].rs);
}
int Query(int x,int l,int r,int K)
{
    if(l==r)return l;
    int mid=(l+r)>>1;
    if(K<=t[t[x].ls].v)return Query(t[x].ls,l,mid,K);
    else return Query(t[x].rs,mid+1,r,K-t[t[x].ls].v);
}
int f[MAX],rt[MAX];
int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)
    {
        int x=read();a[x]=i;
        Modify(rt[f[i]=i],1,n,x);
    }
    while(m--)
    {
        int a=read(),b=read();
        a=getf(a);b=getf(b);
        if(a==b)continue;
        f[b]=a;
        MergeNode(rt[a],rt[b]);
    }
    Q=read();
    char opt[5];
    while(Q--)
    {
        scanf("%s",opt);
        if(opt[0]=='Q')
        {
            int x=read(),k=read();
            x=getf(x);
            if(t[rt[x]].v<k)puts("-1");
            else printf("%d\n",a[Query(rt[x],1,n,k)]);
        }
        else
        {
            int u=read(),v=read();
            u=getf(u),v=getf(v);
            if(u==v)continue;
            f[v]=u;
            MergeNode(rt[u],rt[v]);
        }
    }
    return 0;
}
相關文章
相關標籤/搜索