您的位置:首页 > 其它

UVALive 4730 -树状数组+带权并查集

2016-08-18 23:19 344 查看
题意:有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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: