1. 程式人生 > >UVALive 4730 -樹狀陣列+帶權並查集

UVALive 4730 -樹狀陣列+帶權並查集

題意:有T組測試資料,每組資料的N表示有N個城市,接下來的N行裡每行給出每個城市的座標(0<=x,y<=1000000),然後有M(1<M<200000)個操作,操作有兩類,

1)"road A B",表示將城市A和城市B通過一條道路連線,如果A和B原來屬於不同的城市群,經過這個操作,A和B就在一個城市群裡了,保證每條道路不會和其他道路相交(除了端點A和B)。

(2)"line C",表示查詢當穿過y=C的直線,有多少個城市群、這幾個城市群一共有多少個城市。

以C建立一顆線段樹,

 每次 road A,B 操作,會新生成一個洲,那麼對於這個洲,我們用並查集維護其城市數量num,和其最下、最上延伸範圍sonl,sonr,也就是說這個新的洲會覆蓋 【sonl,sonr】這個範圍,那麼我們在一顆樹狀數組裡 這個範圍的 洲數量 add 1, 另一個樹狀數組裡(管轄城市數量的),add num

ps:當前生成之前的,A,B所在的洲要先抹去掉。

對於查詢line C,直接分別在兩棵樹分別查詢兩個資訊即可

範圍有點大,離散化一下即可。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define  inf 0x7fffffff
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
int n,m;
class Tree
{
    int tree[100131+50];
public:
    void init()
    {
        memset(tree,0,sizeof tree);
    }
    int lowbit(int x)
    {
        return x&-x;
    }
    void add(int x,int value)
    {
        for (int i=x; i<=100000; i=i+lowbit(i))
        {
            tree[i]+=value;
        }
    }
    int get(int x)
    {
        int sum=0;
        for (int i=x; i; i-=lowbit(i))
        {
            sum+=tree[i];
        }
        return sum;
    }

};
Tree tp1,tp2;
int fa[100132];
int sonl[100132];
int sonr[100131];
int num[100132];
int find(int x)
{
    if (x==fa[x]) return x;
    else  return fa[x]=find(fa[x]);
}
int city[100132][2];
void Union(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if (fx==fy) return;
    tp1.add(sonl[fx],-1);
    tp1.add(sonr[fx]+1-1,1);
    tp1.add(sonl[fy],-1);
    tp1.add(sonr[fy]+1-1,1);
    tp2.add(sonl[fx],-num[fx]);
    tp2.add(sonr[fx]+1-1,num[fx]);
    tp2.add(sonl[fy],-num[fy]);
    tp2.add(sonr[fy]+1-1,num[fy]);

    sonl[fy]=min(sonl[fy],sonl[fx]);
    sonr[fy]=max(sonr[fy],sonr[fx]);
    num[fy]+=num[fx];
    fa[fx]=fy;
    tp1.add(sonl[fy],1);
    tp1.add(sonr[fy]+1-1,-1);
    tp2.add(sonl[fy],num[fy]);
    tp2.add(sonr[fy]+1-1,-num[fy]);
    return  ;
}
int bb[100132];
int idx[100132];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        tp1.init();
        tp2.init();
        cin>>n;
        int x,y;
        char tmp[15];

        for (int i=1; i<=n; i++)
            scanf("%d%d",&city[i][0],&city[i][1]);
        for (int i=1; i<=n; i++ ) bb[i]=city[i][1];
        sort(bb+1,bb+1+n);
        int cun=unique(bb+1,bb+1+n)-bb-1;
        for (int i=1;i<=n;i++)
        {
            int id=lower_bound(bb+1,bb+1+cun,city[i][1])-bb;
            idx[i]=id;
        }
        for (int i=1; i<=n; i++) fa[i]=i,sonl[i]=sonr[i]=idx[i],num[i]=1;
        int m;
        cin>>m;
        for (int i=1; i<=m; i++)
        {
            scanf("%s",tmp);
            if (tmp[0]=='r')
            {
                scanf("%d%d",&x,&y);
                x++,y++;
                Union(x,y);
            }
            else
            {
                scanf("%d.5",&x);
                x=upper_bound(bb+1,bb+1+cun,x)-bb;
                x--;
                int ans1=tp1.get(x);
                int ans2=tp2.get(x);
                printf("%d %d\n",ans1,ans2);
            }
        }
    }


    return 0;
}