C. Colorful Table CodeTON Round 6 (Div. 1 + Div. 2, Rated, Prizes!)

题目大意:有一个n个数的数组a,每个数大小不超过k,构建一个n*n的方阵b,其中每个元素b[i,j]=min(a[i],a[j]),求对于1~k的每一个数x,包含矩阵中所有x的最小的矩形的宽+长的值

1<=n,k<=1e5

思路:通过观察可以发现,这个方阵是关于左上-右下的直线对称的,所以我们要找的矩形都是正方形,因为方阵中的值是取最小值得来的,所以每个数构成的正方形的边界就是a中最左边和最右边大于该数的位置,那么问题就转化成了在数组中求每个数最左和最右边大于这个数的位置之间的长度。

首先考虑每个数的左边界怎么求,因为每个数的边界都是最靠左的那个,所以从左向右遍历,我们每遇到一个没处理过的数,所有小于等于这个数的数的左边界都是这个位置,然后这些数都被标记为已处理。

右边界也依照此法从右向左遍历,这样我们就得到了每个数构成的正方形的边长为右边界-左边界+1,再乘二就是答案。

cpp 复制代码
//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
ll n;
ll a[N];
int l[N], r[N];
bool vis[N];
int k;
void init()
{
	for (int i = 1; i <= k; i++)
	{
		vis[i] = 0;
	}
}
void solve()
{
	cin >> n >> k;
	init();
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		vis[a[i]] = 1;//记录一下哪些数在数组中出现过
	}
	int now = 1;
	for (int i = 1; i <= n; i++)
	{		
		while (now <= a[i])
		{
			l[now] = i;//更新所有小于等于这个数的数的左边界
			now++;
		}
	}
	now = 1;
	for (int i = n; i >= 1; i--)
	{
		while (now <= a[i])
		{
			r[now] = i;
			now++;
		}
	}
	for (int i = 1; i <= k; i++)
	{
		if (!vis[i])
		{//没出现的数就是0
			cout << 0 << " ";
			continue;
		}
		cout << (r[i] - l[i] + 1) * 2 << " ";
	}
	cout << endl;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin>>t;
	while (t--)
	{
		solve();
	}
	return 0;
}



 
相关推荐
菜菜的顾清寒几秒前
力扣Hot100(23)反转链表
算法·leetcode·链表
Michelle80231 分钟前
基于随机森林的乳腺癌肿瘤分类实验
算法·随机森林·分类
Yvonne爱编码5 分钟前
机器学习---聚类四大算法完整实验教程(层次 / K-Means/GMM/ 谱聚类)
算法·机器学习·聚类
東隅已逝,桑榆非晚6 分钟前
C语言内存函数
c语言·开发语言·笔记·算法
深蓝电商API10 分钟前
爬虫代理IP智能调度:基于响应速度的实时评分算法
爬虫·算法
Oj92q85H511 分钟前
如何在Dev-C++中设置TDM-GCC为默认编译器
java·jvm·c++
汉克老师11 分钟前
GESP5级C++考试语法知识(十七、二分算法提高篇(一))
c++·算法·二分算法·gesp5级·gesp五级·二分算法易错点
灵智实验室11 分钟前
PX4状态估计技术EKF2详解(五):EKF2 故障检测、重置与鲁棒性——从单实例到多实例仲裁
算法·无人机·px 4
programhelp_16 分钟前
Roblox Coding OA 面经分享|题量不小,但整体更偏工程思维
人工智能·算法·面试
周末也要写八哥17 分钟前
机器学习评价指标之平均概念
人工智能·算法·机器学习