UVALive 4730 -樹狀陣列+帶權並查集
阿新 • • 發佈:2019-01-21
題意:有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; }