G题 - Wall Game题解 第18届浙江省程序设计竞赛(ZJCPC:The 18th Zhejiang Provincial Collegiate Programming Contest

题面(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;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值