[题解][Codeforces 1137A~1137F]Codeforces Round #545 (Div. 1) 简要题解

这篇博客详细介绍了Codeforces Round #545 (Div. 1)比赛中的六道题目,包括题意、算法思路和代码实现。涉及的算法包括KMP、Tarjan、Floyd判圈、维护凸壳和LCT等,适合程序员进阶学习。
摘要由CSDN通过智能技术生成
  • 第一次打 Div. 1 ,感觉题目质量还是比较好的
  • 然后就把我这个菜鸡选手区分到了榜末

题目

洛谷 RemoteJudge

Codeforces

A

题意

  • 一个 n × m n\times m n×m 矩阵 a a a
  • 定义 f ( x , y ) f(x,y) f(x,y) 表示在矩阵中取出第 x x x 行和第 y y y
  • 设一个新矩阵 b b b ,这个矩阵只有第 x x x 行和第 y y y
  • 对于 b b b 中的任意两个元素 b i , j b_{i,j} bi,j b u , v b_{u,v} bu,v
  • 如果 b i , j &lt; b u , v b_{i,j}&lt;b_{u,v} bi,j<bu,v a i , j a_{i,j} ai,j 必须小于 a u , v a_{u,v} au,v
  • 如果 b i , j = b u , v b_{i,j}=b_{u,v} bi,j=bu,v a i , j a_{i,j} ai,j 必须等于 a u , v a_{u,v} au,v
  • &gt; &gt; > 同理
  • f ( x , y ) f(x,y) f(x,y) 等于矩阵 b b b 所有合法的方案中, b b b 中最大元素的最小值
  • 对于每个 1 ≤ x ≤ n , 1 ≤ y ≤ m 1\le x\le n,1\le y\le m 1xn,1ym f ( x , y ) f(x,y) f(x,y)
  • 1 ≤ n , m ≤ 1000 1\le n,m\le 1000 1n,m1000

题解

  • 显然,我们要求的是
  • max ⁡ ( 第 x 行 比 a x , y 小 的 数 个 数 , 第 y 列 比 a x , y 小 的 数 个 数 ) + 1 \max(第x行比a_{x,y}小的数个数,第y列比a_{x,y}小的数个数)+1 max(xax,y,yax,y)+1
  • + max ⁡ ( 第 x 行 比 a x , y 大 的 数 个 数 , 第 y 列 比 a x , y 大 的 数 个 数 ) +\max(第x行比a_{x,y}大的数个数,第y列比a_{x,y}大的数个数) +max(xax,y,yax,y)
  • max ⁡ \max max 里面的四个东西都可以把矩阵的每行每列离散化之后求出
  • O ( n m ( log ⁡ n + log ⁡ m ) ) O(nm(\log n+\log m)) O(nm(logn+logm))

代码

#include <bits/stdc++.h>

// 20030830

inline int read()
{
   
	int res = 0; bool bo = 0; char c;
	while (((c = getchar()) < '0' || c > '9') && c != '-');
	if (c == '-') bo = 1; else res = c - 48;
	while ((c = getchar()) >= '0' && c <= '9')
		res = (res << 3) + (res << 1) + (c - 48);
	return bo ? ~res + 1 : res;
}

const int N = 1005;

int n, m, a[N][N], cntx[N], cnty[N], thx[N][N], thy[N][N], w[N];

int main()
{
   
	n = read(); m = read();
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			a[i][j] = read();
	for (int i = 1; i <= n; i++)
	{
   
		for (int j = 1; j <= m; j++) w[j] = a[i][j];
		std::sort(w + 1, w + m + 1);
		cntx[i] = std::unique(w + 1, w + m + 1) - w - 1;
		for (int j = 1; j <= m; j++)
			thx[i][j] = std::lower_bound(w + 1, w + cntx[i] + 1, a[i][j]) - w;
	}
	for (int i = 1; i <= m; i++)
	{
   
		for (int j = 1; j <= n; j++) w[j] = a[j][i];
		std::sort(w + 1, w + n + 1);
		cnty[i] = std::unique(w + 1, w + n + 1) - w - 1;
		for (int j = 1; j <= n; j++)
			thy[j][i] = std::lower_bound(w + 1, w + cnty[i] + 1, a[j][i]) - w;
	}
	for (int i = 1; i <= n; i++)
	{
   
		for (int j = 1; j <= m; j++)
			printf("%d ", std::max(thx[i][j], thy[i][j])
				+ std::max(cntx[i] - thx[i][j], cnty[j] - thy[i][j]));
		puts("");
	}
	return 0;
}

B

题意

  • 两个 01 01 01 s s s t t t
  • 构造一个串,满足
  • (1) 该串中 0 0 0 的个数和 1 1 1 的个数都与 s s s 一样多
  • (2) t t t 在该串中出现的次数最多
  • 1 ≤ ∣ s ∣ , ∣ t ∣ ≤ 500000 1\le|s|,|t|\le500000 1s,t500000

算法: KMP + 贪心

  • 问题可以看成一个完整的 t t t 串,后面接上一些
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值