题面(The Problem)
题意(The Meaning of the problem.)
n组输入,每组输入三个数字,第一个数字代表操作类型, 第二三个数字代表坐标:
操作1:
在整个图上添加点,并和相邻的点联通
操作2:
查询这个点的整个联通的快,输出整个块的边的数量
解题思路(The Thinking of Solving the Problem)
思路是用并查集维护,因为输入正负1e9所以要做离散化。我的思路是用结构体表示点,用map维护node映射到node的数组里面。
(很多人都是3秒多过的,不知道为什么我是一秒出头)
代码(Code)
#include "bits/stdc++.h"
using namespace std;
const int MAXN = 5e5 + 6;
int moveN[6][2] = {{1, 0}, {1, -1}, {0, -1}, {-1, 0}, {-1, 1}, {0, 1}};
struct node {
int x, y;
node(){}
node(int a, int b) : x(a), y(b){}
bool operator < (node const b) const {
if (x == b.x) return y < b.y;
return x < b.x;
}
}A[MAXN];
int num[MAXN], value[MAXN], pre[MAXN];
map<node, int>mpKey;
int find(int x) {
if (pre[x] == x || pre[x] == 0) {
return pre[x] = x;
}
return pre[x] = find(pre[x]);
}
void query(int x, int y) {
static int cnt = 0;
A[++cnt] = (node){x, y};
mpKey[(node{x, y})] = cnt;
num[cnt] = 1;
value[cnt] = 0;
for (int i = 0; i < 6; ++i) {
int nowx = x + moveN[i][0], nowy = y + moveN[i][1];
if (mpKey.find((node){nowx, nowy}) == mpKey.end()) {
continue;
}
int nowkey = find(mpKey[(node){nowx, nowy}]);
if (nowkey != cnt) {
pre[nowkey] = cnt;
value[cnt] += value[nowkey] + 2;
num[cnt] += num[nowkey];
//cout << num[cnt] << endl;
}else {
value[cnt] += 2;
}
}
return;
}
int main(void) {
int t;
cin >> t;
while (t--) {
int a, x, y;
scanf("%d %d %d", &a, &x, &y);
if (a == 1) {
query(x, y);
}else {
node now = {x, y};
if (mpKey.find(now) == mpKey.end()) {
cout << 6 << endl;
}else {
int key = find(mpKey[now]);
//cout << key << endl;
//cout << "num:" << num[key] << " value" << value[key] << endl;
cout << num[key] * 6 - value[key] << endl;
}
}
}
// for (int i = 0; i < 10; ++i) {
// cout << "num:" << num[i] << " value:" << value[i] << endl;
// }
return 0;
}