2021.4 ICPC昆明站L:Simone and graph coloring

problem title:Simone and graph coloring
题目描述
Simone, a student of Graph Coloring University, is interested in permutation. Now she is given a permutation of length nn, and she finds that if she connects each inverse pair, she will get a graph. Formally, for the given permutation, if i<j && Ai >Aj , then there will be an undirected edge between node iand node j in the graph.
Then she wants to color this graph. Please achieve poor Simone’s dream. To simplify the problem, you just need to find a way of coloring the vertices of the graph such that no two adjacent vertices are of the same color and minimize the number of colors used.

输入描述:
There are multiple test cases. The first line of the input contains an integer T(1≤T≤10^6 ), indicating the number of test cases.
For each test case, the first line contains an integer n1≤n≤10 ^6), indicating the length of the permutation.

The second line contains nn integers A1,A2…An , indicating the permutation.It is guaranteed that the sum of nn over all test cases does not exceed 10^6
.
输出描述:
for each case:
the first line is the kind of color you need.
the second line is C1,C2,…,Cn,insrruction the color of nood i(1,2…,n).
the answer is not sole.Out put any of them.
题解:
本道题求的是全排列数列,每对逆序对的标号之间有一条无向边,给所有标号涂色,有无向边相连的两个标号不能是同一种颜色,最少要几种颜色,以及具体的方案。
我们用数字表示 不同的颜色,第一钟颜色为1,第二种颜色为2,以此类推。
令第i个标号所对应要涂的颜色为Ci。对于每一个数,标号为i(第i个),则j<i,Aj>Ai,就是逆序对。对于所有的逆序数标号j,取出对应的Cj最大的那一个,Ci一定满足Ci=Cj+1(因为j在i前面,比Cj小的颜色都已经涂在j往前的逆序对数上了,而这些数一定也会和i对应的Ai形成逆序对),其中最大的Ci,就是需要颜色的种类。
对于每一个位置i,现在我们只要用树状数组存(n>=Aj>Ai)&&(j<i)所有满足的j中最大的Cj即可。


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M = 1e6 + 5;
int c[M];//树状数组
int ans[M];//ans数组是文中的序列C。
int n;
int ansl;
inline int query(int x)
{
	int res = 0;

	for (; x>0; x -= (x & (-x)))
	{
		
		res = max(c[x], res);
	}
	return res;
}
inline void update(int x, int val)
{
	for (; x <= n; x += (x & (-x)))
	{
	
		c[x] = max(c[x], val);
	}
}
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int main()
{
	int t;
	t=read();
	while (t--)
	{
		n=read();
	
        for(int i=0;i<=n;i++)c[i]=0;
	
		ansl = 0;
		
		for (int i = 1; i <= n; i++)
		{
			ans[0]=read();
			ans[i] = query(n - ans[0]) + 1;
			//找最大的Cj。Ci=Cj+1.
			ansl = max(ans[i], ansl);//最大的Ci
			update(n - ans[0] + 1, ans[i]);//插入Ci
		}
		printf("%d\n", ansl);
		for (int i = 1; i <= n; i++)
		{
			if (i == 1)printf("%d", ans[i]);
			else printf(" %d", ans[i]);
		}
		printf("\n");
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值