最长上升下降子序列问题

该博客主要讨论图着色问题,通过解决一个关于给定排列的图着色问题来找到最小颜色数。首先,从排列中构建一个图,其中每个节点与其逆序对相连。然后,通过动态规划计算每个节点的最大下降子序列长度,这同时给出了图的着色方案,确保相邻节点颜色不同。最后,输出最小颜色数及其对应的节点颜色。
摘要由CSDN通过智能技术生成

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

Simone, a student of Graph Coloring University, is interested in permutation. Now she is given a permutation of length nnn, and she finds that if she connects each inverse pair, she will get a graph. Formally, for the given permutation, if i<ji<ji<j and ai>aja_i>a_jai​>aj​, then there will be an undirected edge between node iii and node jjj 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≤106)T(1\leq T\leq 10^6)T(1≤T≤106), indicating the number of test cases. 

For each test case, the first line contains an integer n(1≤n≤106)n(1 \leq n \leq 10^6)n(1≤n≤106), indicating the length of the permutation. 

The second line contains nnn integers a1,a2,...,ana_1,a_2,...,a_na1​,a2​,...,an​, indicating the permutation.

It is guaranteed that the sum of nnn over all test cases does not exceed 10610^6106.

输出描述:

For each test case, the first line contains an integer ccc, the chromatic number(the minimal number of colors been used when coloring) of the graph.

The second line contains nnn integers c1,c2,...,cnc_1,c_2,...,c_nc1​,c2​,...,cn​, the color of each node.

Notice that cic_ici​ should satisfy the limit that 1≤ci≤c1 \leq c_i \leq c1≤ci​≤c.

If there are several answers, it is acceptable to print any of them. 
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e6+5;
int b[maxn];
int f[maxn];//以i为结尾的最长下降子序列
int main()
{
    int t;cin>>t;
    while(t--)
    {
        int n;cin>>n;
        int tot=1;
        scanf("%d",&b[1]);f[1]=1;
        for(int i=2;i<=n;i++)
        {
            int num;scanf("%d",&num);
            if(num<b[tot])
            {
                b[++tot]=num;
                f[i]=tot;
            }
            else
            {
                int l=1,r=tot;
                int pos;
                while(l<=r)
                {
                    int m=(l+r)/2;
                    if(b[m]<=num)
                    {
                        pos=m;
                        r=m-1;
                    }
                    else
                    {
                        l=m+1;
                    }
                }
                b[pos]=num;
                f[i]=pos;
            }
        }
        printf("%d\n",tot);
        for(int i=1;i<=n;i++)
        {
            printf("%d ",f[i]);
        }
        printf("\n");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值