UVALive 4730 Kingdom 线段树+并查集

题目链接:点击打开链接

题意见白书P248

思路:

先把读入的y值都扩大2倍变成整数

然后离散化一下

用线段树来维护y轴 区间上每个点的 城市数量和联通块数量,

然后用并查集维护每个联通块及联通块的最大最小y值,还要加并查集的秩来记录每个联通块的点数


然后就是模拟搞。。

T^T绝杀失败题。。似乎数组开小了一点就过了,==

#include<stdio.h>
#include<math.h>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
#define rank Rank
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Lson(x) tree[x].l
#define Rson(x) tree[x].r
#define Sum0(x) tree[x].sum[0]
#define Lazy0(x) tree[x].lazy[0]
#define Sum1(x) tree[x].sum[1]
#define Lazy1(x) tree[x].lazy[1]
inline int Mid(int x, int y){return (x+y)>>1;}
#define N 100005
struct Point{
	int x, y;
}p[100005];
struct que{
	int u, v, op;
}Q[200005];
vector<int>G;
int n, q;
char s[10];

struct node{
	int l, r, sum[2], lazy[2];
}tree[N<<4];
void push_down(int id){
	if(Lazy1(id)) {
		Sum1(L(id)) += Lazy1(id);
		Sum1(R(id)) += Lazy1(id);
		Lazy1(L(id)) += Lazy1(id);
		Lazy1(R(id)) += Lazy1(id);
		Lazy1(id) = 0;
	}
	if(Lazy0(id)) {
		Sum0(L(id)) += Lazy0(id);
		Sum0(R(id)) += Lazy0(id);
		Lazy0(L(id)) += Lazy0(id);
		Lazy0(R(id)) += Lazy0(id);
		Lazy0(id) = 0;
	}
}
void push_up(int id){Sum0(id) = Sum0(L(id)) + Sum0(R(id));Sum1(id) = Sum1(L(id)) + Sum1(R(id));}
void build(int l, int r, int id){
	Lson(id) = l; Rson(id) = r;
	Sum0(id) = Lazy0(id) = Sum1(id) = Lazy1(id) = 0;
	if(l == r) return ;
	int mid = Mid(l, r);
	build(l, mid, L(id));
	build(mid+1, r, R(id));
}
void updata(int l, int r, int val, int now, int id){
	push_down(id);
	if(l == Lson(id) && Rson(id) == r) {
		if(now==0)Sum0(id) += val, Lazy0(id) += val;
		else Sum1(id) += val, Lazy1(id) += val;
		return ;
	}
	int mid = Mid(Lson(id), Rson(id));
	if(mid < l)
		updata(l, r, val, now, R(id));
	else if(r <= mid)
		updata(l, r, val, now, L(id));
	else {
		updata(l, mid, val, now, L(id));
		updata(mid+1, r, val, now, R(id));
	}
	push_up(id);
}
int query(int pos, int now, int id){
	push_down(id);
	if(Lson(id)==Rson(id))if(now==0)return Sum0(id); else return Sum1(id);
	int mid = Mid(Lson(id), Rson(id));
	int ans;
	if(mid < pos)
		return query(pos, now, R(id));
	else return query(pos, now, L(id));
}
int f[100005], rank[100005], S[100005], X[100005]; //每个集合的上下界
int find(int x){return x==f[x]?x:f[x] = find(f[x]);}
void Union(int x, int y){
	int fx = find(x), fy = find(y);
	if(fx == fy)return;
	if(S[fx] > S[fy]) swap(fx, fy);
	if(S[fx] <= X[fy]){
		updata(S[fx], X[fy], 1, 0, 1);
		updata(S[fx], X[fy], rank[fx] + rank[fy], 1, 1);
		updata(X[fx], S[fx], rank[fy], 1, 1);
		updata(X[fy], S[fy], rank[fx], 1, 1);
	}
	else if(X[fx] >= X[fy]) {
		updata(X[fx], S[fx], -1, 0, 1);
		updata(X[fy], X[fx], rank[fx], 1, 1);
		updata(S[fx], S[fy], rank[fx], 1, 1);
	}
	else {
		updata(X[fy], S[fx], -1, 0, 1);
		updata(X[fx], X[fy], rank[fy], 1, 1);
		updata(S[fx], S[fy], rank[fx], 1, 1);
	}
	if(rank[fy]<rank[fx])swap(fx, fy);
	f[fx] = fy;
	rank[fy] += rank[fx];
	rank[fx] = 0;
	X[fy] = min(X[fy], X[fx]);
	S[fy] = max(S[fy], S[fx]);
}

void input(){
	G.clear();
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) f[i] = i, rank[i] = 1;
	for(int i = 1; i <= n; i++) scanf("%d %d",&p[i].x, &p[i].y), p[i].y <<= 1, G.push_back(p[i].y);
	scanf("%d", &q);
	for(int i = 0; i < q; i++)
	{
		scanf("%s", s);
		if(s[0]=='r')
		{
			Q[i].op = 1;
			scanf("%d %d", &Q[i].u, &Q[i].v); Q[i].u++; Q[i].v++;
		}
		else {
			Q[i].op = 2;
			scanf("%d.5",&Q[i].u);
			Q[i].u = Q[i].u * 2+1;
			G.push_back(Q[i].u);
		}
	}
	sort(G.begin(), G.end());
	G.erase(unique(G.begin(), G.end()), G.end());
	for(int i = 1; i <= n; i++)X[i] = S[i] = p[i].y = lower_bound(G.begin(), G.end(), p[i].y) - G.begin()+1;
	for(int i = 0; i < q; i++)if(Q[i].op == 2)Q[i].u = lower_bound(G.begin(), G.end(), Q[i].u) - G.begin()+1;
}
int main() {
	int T; scanf("%d",&T);
	while(T--){
		input();
		build(1, G.size(), 1);
		for(int i = 0; i < q; i++) {
			if(Q[i].op == 1)
			{
				Union(Q[i].u, Q[i].v);
			}
			else
				printf("%d %d\n", query(Q[i].u, 0, 1), query(Q[i].u, 1, 1));
		}
	}
	return 0;
}
/*
3 
11
1 7 
5 7 
8 6 
3 5 
5 5 
2 3 
10 3 
7 2 
4 1 
11 1 
4 6
21
road 0 1 
road 3 5 
line 6.5 
road 4 2 
road 3 8 
road 4 7 
road 6 9 
road 4 1 
road 2 7 
line 4.5 
line 6.5 
line 3.5
line 2.5
line 5.5
road 10 0
line 5.5
line 6.5
road 0 3
line 1.5
line 6.5
line 2.5

ans:
0 0 
2 8 
1 5 
2 8
3 10
1 5
1 6
1 6
2 11
1 9
2 11


*/


你可能感兴趣的:(UVALive 4730 Kingdom 线段树+并查集)