首页 > 其他分享 >CodeForces 1920F2 Smooth Sailing (Hard Version)

CodeForces 1920F2 Smooth Sailing (Hard Version)

时间:2024-01-14 15:11:06浏览次数:35  
标签:Sailing int top Hard Smooth tot edge maxn ID

洛谷传送门

CF 传送门

首先需要知道的一个 trick:判断一个点是否在一个闭合回路内部,从这个点向任意方向引一条射线,若不考虑相切,那么和回路的交点为奇数时这个点在回路内部,否则在外部。

那么这题要判断一个回路是否包含全部的 island,可以找到任意一个 island 向右引一条射线。

给每个点增加一个状态 \((x, y, 0/1)\) 表示当前走到 \((x, y)\),经过了偶数或奇数次射线。那么依次询问的本质是找到一条 \((x, y, 0) \to (x, y, 1)\) 的一条经过点权最小值最大的路径(可以多源 bfs 求出任意一点 \((i, j)\) 到最近的 v 的距离 \(d_{i, j}\),\((x, y, 0/1)\) 的点权就是 \(d_{x, y}\))。

上面那个问题显然给每条 \((u, v)\) 赋权 \(\min(val_u, val_v)\),就可以建 Kruskal 重构树查 LCA 解决。

建图就对于一个 \((x, y)\),如果它在射线上就视为 \((x, y) \to (x + 1, y)\) 和射线新增了一个交点。

时间复杂度 \(O((nm + q) \log nm)\)。

code
// Problem: F2. Smooth Sailing (Hard Version)
// Contest: Codeforces - Codeforces Round 919 (Div. 2)
// URL: https://codeforces.com/contest/1920/problem/F2
// Memory Limit: 1024 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define ID(x, y) (((x) - 1) * m + (y))
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<int, int> pii;

const int maxn = 1200100;
const int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};

int n, m, q, f[maxn], tot, ff[maxn];
string s[maxn];

struct edge {
	int u, v, d;
	edge(int a = 0, int b = 0, int c = 0) : u(a), v(b), d(c) {}
} E[maxn * 5];

vector<int> G[maxn];
int fa[maxn], sz[maxn], son[maxn], dep[maxn], top[maxn], a[maxn];

int dfs(int u, int f, int d) {
	fa[u] = f;
	sz[u] = 1;
	dep[u] = d;
	int mx = -1;
	for (int v : G[u]) {
		if (v == f) {
			continue;
		}
		sz[u] += dfs(v, u, d + 1);
		if (sz[v] > mx) {
			son[u] = v;
			mx = sz[v];
		}
	}
	return sz[u];
}

void dfs2(int u, int tp) {
	top[u] = tp;
	if (!son[u]) {
		return;
	}
	dfs2(son[u], tp);
	for (int v : G[u]) {
		if (!top[v]) {
			dfs2(v, v);
		}
	}
}

inline int qlca(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) {
			swap(x, y);
		}
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) {
		swap(x, y);
	}
	return x;
}

int find(int x) {
	return ff[x] == x ? x : ff[x] = find(ff[x]);
}

void solve() {
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1; i <= n * m * 4; ++i) {
		ff[i] = i;
	}
	int X = -1, Y = -1;
	for (int i = 1; i <= n; ++i) {
		cin >> s[i];
		s[i] = " " + s[i] + " ";
		for (int j = 1; j <= m; ++j) {
			if (s[i][j] == '#') {
				X = i;
				Y = j;
			}
		}
	}
	queue<pii> Q;
	mems(f, -1);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			if (s[i][j] == 'v') {
				f[ID(i, j)] = 0;
				Q.emplace(i, j);
			}
		}
	}
	while (Q.size()) {
		int x = Q.front().fst, y = Q.front().scd;
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 1 || nx > n || ny < 1 || ny > m) {
				continue;
			}
			if (f[ID(nx, ny)] == -1) {
				f[ID(nx, ny)] = f[ID(x, y)] + 1;
				Q.emplace(nx, ny);
			}
		}
	}
	int tot = 0;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			if (s[i][j] == '#') {
				continue;
			}
			if (i < n && s[i + 1][j] != '#') {
				int d = min(f[ID(i, j)], f[ID(i + 1, j)]);
				if (i == X && j > Y) {
					E[++tot] = edge(ID(i, j), ID(i + 1, j) + n * m, d);
					E[++tot] = edge(ID(i, j) + n * m, ID(i + 1, j), d);
				} else {
					E[++tot] = edge(ID(i, j), ID(i + 1, j), d);
					E[++tot] = edge(ID(i, j) + n * m, ID(i + 1, j) + n * m, d);
				}
			}
			if (j < m && s[i][j + 1] != '#') {
				int d = min(f[ID(i, j)], f[ID(i, j + 1)]);
				E[++tot] = edge(ID(i, j), ID(i, j + 1), d);
				E[++tot] = edge(ID(i, j) + n * m, ID(i, j + 1) + n * m, d);
			}
		}
	}
	sort(E + 1, E + tot + 1, [&](const edge &a, const edge &b) {
		return a.d > b.d;
	});
	int nt = n * m * 2;
	for (int i = 1; i <= tot; ++i) {
		int x = find(E[i].u), y = find(E[i].v), d = E[i].d;
		if (x != y) {
			int z = ++nt;
			ff[x] = ff[y] = z;
			a[z] = d;
			G[z].pb(x);
			G[z].pb(y);
		}
	}
	dfs(nt, -1, 1);
	dfs2(nt, nt);
	while (q--) {
		int x, y;
		scanf("%d%d", &x, &y);
		printf("%d\n", a[qlca(ID(x, y), ID(x, y) + n * m)]);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:Sailing,int,top,Hard,Smooth,tot,edge,maxn,ID
From: https://www.cnblogs.com/zltzlt-blog/p/17963744

相关文章

  • P9007 [入门赛 #9] 最澄澈的空与海 (Hard Version) 题解
    Updon2023.10.1408:21:修改了推式子和题意的一些小错误。前言一道恐怖的绿题。显然我认为应该是蓝题。(不过在这篇题解写到一半的时候升蓝了,感谢@StudyingFather。)名字挺好的。题意给定\(n\),求出满足以下条件的三元组\((x,y,z)\)的组数:\(x\ge0,z\ge1\)。\(......
  • Hardhat框架使用及生成交易trace
    Hardhat介绍hardhat-tutorial安装Hardhat框架安装nvmbrewinstallnvm~/.zshrc添加nvm配置#NVMCONFIGexportNVM_DIR="$HOME/.nvm" [-s"/usr/local/opt/nvm/nvm.sh"]&&\."/usr/local/opt/nvm/nvm.sh"#Thisloadsnvm [-s"/us......
  • 理解 Apache ShardingSphere 的 SPI,以及为何它比 Dubbo 更简单
    为什么学习ShardingSphere的SPI?你可能已经熟悉Java和Dubbo的SPI(ServiceProviderInterface)机制,所以你可能会想:“为什么要学习ShardingSphere的SPI机制呢?”原因非常简单:ShardingSphere的源代码更简单、更容易适应。ShardingSphere的SPI机制执行非常顺畅,日常操作所......
  • 使用 PostgreSQL 16.1 + Citus 12.1 作为多个微服务的分布式 Sharding 存储后端
    在本教程中,我们将使用PostgreSQL16.1+Citus12.1作为多个微服务的存储后端,演示此类集群的样例设置和基本操作。Citus12.1实验环境设置Docker快速启动Citus分布式集群docker-compose.ymlversion:"3"services:master:container_name:"${COMPOSE_PROJECT_NAME:......
  • Maximum And Queries (hard version)
    题目传送门感觉这题比\(\rmF\)难啊,\(\rmF\)就是个板子,但为啥这题是蓝的,\(\rmF\)是紫的。思路首先考虑\(nq\)怎么做。发现很简单,按位贪心就行了。具体地说,从大到小枚举二进制位,判断答案中能否出现这一位,若\(i\)当前这一位没有值,那么必须被补全到这个值,否则无所谓,然......
  • E2. Game with Marbles (Hard Version)
    E2.GamewithMarbles(HardVersion)Theeasyandhardversionsofthisproblemdifferonlyintheconstraintsonthenumberoftestcasesand$n$.Inthehardversion,thenumberoftestcasesdoesnotexceed$10^4$,andthesumofvaluesof$n$overall......
  • shardingSphere-JDBC 多数据源主从+切片配置
    4.x版本配置maven依赖<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version></dependency>application配置spri......
  • SpringBoot 整合 ShardingSphere JDBC、MySQL分表实例
    1.概述ShardingSphere分为ShardingSphere-JDBC、ShardingSphere-Proxy、ShardingSphere-Sidecar(TODO)。ShardingSphere官方手册:传送门;这里使用的是ShardingSphere-JDBC,ShardingSphere-JDBC为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar......
  • 使用 PostgreSQL 16.1 + Citus 12.1 作为多个微服务的分布式 Sharding 存储后端
    在本教程中,我们将使用PostgreSQL16.1+Citus12.1作为多个微服务的存储后端,演示此类集群的样例设置和基本操作。Citus12.1实验环境设置Docker快速启动Citus分布式集群docker-compose.ymlversion:"3"services:master:container_name:"${COMPOSE_PROJECT......
  • G2. Light Bulbs (Hard Version)
    G2.LightBulbs(HardVersion)Theeasyandhardversionsofthisproblemdifferonlyintheconstraintson$n$.Inthehardversion,thesumofvaluesof$n$overalltestcasesdoesnotexceed$2\cdot10^5$.Furthermore,therearenoadditionalconstr......