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");
}
}