2021ICPC昆明站L-Simone and graph coloring

这篇博客主要探讨了一种图论问题,即给定一个序列,其中每对逆序元素之间存在边,目标是最小化染色所需的颜色数量。通过建立单调栈来寻找以每个节点结尾的最长单调递减子序列,确定每个节点的颜色,从而得出最少颜色数。代码中展示了如何实现这一算法,输出每个节点的颜色和最小颜色数。
摘要由CSDN通过智能技术生成

题目链接

题意:一个序列p,所有的逆序对间直接存在一条边,现在将这些点染色,相邻的点颜色不能相同,问最少用多少种颜色,并输出每个点的颜色

解析:不难想到的是,最少的颜色种类为最长单调递减序列的长度,现在考虑每个点染什么颜色的问题,假设第i个点染得颜色为x,那么i节点之前至少存在一个已i节点结尾的最长单调递减序列,长度为x,因为单调递减序列中的点两两相连,所以需要的颜色为序列的长度。我们通过上述解释可以得到一种涂色方式:某节点的颜色为以该节点结尾的最长单调递减序列的长度。

AcCode

#include<algorithm>
#include<iostream>
#include<vector>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<cstring>
#include<cmath>

#define int long long
const int N = 1e6 + 100;

int value[N];
int output[N];
int arr[N];

signed main() {
	int t;
	std::scanf("%lld", &t);
	while (t--) {
		int n;
		std::cin >> n;
		for (int i = 1; i <= n; i++) std::scanf("%lld", &value[i]);
		output[1] = 1;
		int cnt = 1;
		arr[0] = value[1];
		for (int i = 2; i <= n; i++) {
			if (arr[cnt - 1] > value[i]) {
				arr[cnt++] = value[i];
				output[i] = cnt;
			}
			else {
				int pos = std::upper_bound(arr, arr + cnt, value[i], std::greater<int>()) - (arr);
				arr[pos] = value[i];
				output[i] = pos + 1;
			}
		}
		std::printf("%lld\n", cnt);
		for (int i = 1; i <= n; i++) std::printf("%lld ", output[i]);
		std::printf("\n");
	}

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值