2020ICPC昆明 L.Simone and graph coloring(思维+nlog(n)的最长下降子序列)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020ICPC昆明 L.Simone and graph coloring(思维+nlog(n)的最长下降子序列)相关的知识,希望对你有一定的参考价值。

LINK

给定长度 n n n的数组 a a a

i < j & & a i > a j i<j\\&\\&a_i>a_j i<j&&ai>aj,那么 i , j i,j i,j之间有一条无向边

使用最少的颜色给这个图染色,使得每条边连接的两个顶点颜色都是不同的


这种形如逆序对的连边方式,最后的图应该是一个 D A G DAG DAG

i i i会和 j ∈ [ 1 , i − 1 ] & & a j > a i j\\in[1,i-1]\\&\\&a_j>a_i j[1,i1]&&aj>ai的所有 j j j连边

那么设所有 j j j的颜色是 1 1 1, i i i的颜色是 2 2 2

此时后面有一个 k k k i i i连边,那么也会和前面所有 j j j连边

所以 k k k的颜色是 3 3 3

如此这般,我们发现求一个 D A G DAG DAG上的最长路就好了

而且这个 D A G DAG DAG非常特殊,所以只需要求一个最长上升子序列即可

并且发现,如果令 f [ i ] f[i] f[i]表示以 i i i结尾的最长上升子序列,那么 f i f_i fi也是他的颜色

这样不会引起冲突

但是突然脑瘫不会写 n l o g ( n ) nlog(n) nlog(n)的最长下降子序列

灵机一动把每个数变成 1 0 9 − a i 10^9-a_i 109ai,于是求一个最长上升子序列就好了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int t,n,f[maxn],d[maxn],a[maxn];
int main()
{
	cin >> t;
	while( t-- )
	{
		cin >> n;
		for(int i=1;i<=n;i++)	scanf("%d",&a[i] ),a[i] = 1e9-a[i];
		int ans = 0;
		f[1] = 1, d[++ans] = a[1];
		for(int i=2;i<=n;i++)
		{
			int id = lower_bound( d+1,d+1+ans,a[i] )-d;
			if( id<=ans )	d[id] = a[i];
			else	d[++ans] = a[i];
			f[i] = id;
		} 
		printf("%d\\n",ans);
		for(int i=1;i<=n;i++)	printf("%d ",f[i] );
		puts("");
	}
}

以上是关于2020ICPC昆明 L.Simone and graph coloring(思维+nlog(n)的最长下降子序列)的主要内容,如果未能解决你的问题,请参考以下文章

2020ICPC 昆明热身赛 C.Statues(小思维)

2020ICPC昆明 C.Cities(区间dp)

2020ICPC 昆明 M.Stone Games(思维+可持久化线段树)

ACM周赛&ICPC昆明资格赛

ICPC20昆明M——动态开点权值线段树(主席树)

2021 ICPC昆明 Stone Games(主席树)