【CodeForce 1213F】 Unstable String Sort | 强连通分量、拓扑排序

Authors have come up with the string ss consisting of nn lowercase Latin letters.

You are given two permutations of its indices (not necessary equal) pp and qq (both of length nn). Recall that the permutation is the array of length nn which contains each integer from 11 to nn exactly once.

For all ii from 11 to n−1n−1 the following properties hold: s[pi]≤s[pi+1]s[pi]≤s[pi+1] and s[qi]≤s[qi+1]s[qi]≤s[qi+1]. It means that if you will write down all characters of ss in order of permutation indices, the resulting string will be sorted in the non-decreasing order.

Your task is to restore any such string ss of length nn consisting of at least kk distinct lowercase Latin letterswhich suits the given permutations.

If there are multiple answers, you can print any of them.

Input

The first line of the input contains two integers nn and kk (1≤n≤2⋅105,1≤k≤261≤n≤2⋅105,1≤k≤26) — the length of the string and the number of distinct characters required.

The second line of the input contains nn integers p1,p2,…,pnp1,p2,…,pn (1≤pi≤n1≤pi≤n, all pipi are distinct integers from 11 to nn) — the permutation pp.

The third line of the input contains nn integers q1,q2,…,qnq1,q2,…,qn (1≤qi≤n1≤qi≤n, all qiqi are distinct integers from 11 to nn) — the permutation qq.

Output

If it is impossible to find the suitable string, print "NO" on the first line.

Otherwise print "YES" on the first line and string ss on the second line. It should consist of nn lowercase Latin letters, contain at least kk distinct characters and suit the given permutations.

If there are multiple answers, you can print any of them.

Example

Input

3 2
1 2 3
1 3 2

Output

YES
abb

题意:给你一段序列,让你求最少用k个字母构成一个字符串,这个字符串满足 s[p[i]]<=s[p[i+1]]  s[q[i]]<=s[q[i+1]];

题目思路:

首先建图,a->b建边 表示是s[a]<=s[b] 然后求强连通分量 ,任何一个强连通分量内 绝对字母都一样 

然后 对强连通分量进行缩点,判断一下强连通分量的个数如果<k ,那么问题无解,如果<=k,他说至少用k个字母,那咱们就用k个字母,而且强连通分量之间是单向联通的关系.所以拓扑图排序一下,然后将前k-1个不同,后面全都相同即可.

//#include <bits/stdc++.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string.h>
#pragma GCC optimize(2)
typedef long long ll;
typedef unsigned long long ull;
const int mod=1000;
const int maxn=1e6+5;
const ll INF=100000000000005;
using namespace std;
ll n,m,p;
int head[maxn];
int head1[maxn];
ll cnt=0,cnt1=0;
struct node{
    int e,next;
}edge[maxn],edge1[maxn];
int dfn[maxn],low[maxn];//dfs序号 他能连接到的最小根节点
int st[maxn],s=0;//栈
int sct[maxn],szsc[maxn],scc=0;//强连通分量所属,强连通分量个数
int inst[maxn];//标记是否在栈中
int cot=0;//标记DFS序
int res[maxn];
int in[maxn];
int vis[maxn];
void addedge1(int u,int v)
{
    edge1[cnt1].e=v;
    edge1[cnt1].next=head1[u];
    head1[u]=cnt1++;
}
void addedge(int u,int v)
{
    edge[cnt].e=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void Tarjan(int u)
{
    st[++s]=u;inst[u]=1;
    low[u]=dfn[u]=++cot;
    for(int i=head[u];~i;i=edge[i].next)
    {
        int e=edge[i].e;
        if(!dfn[e])
        {
            Tarjan(e);
            low[u]=min(low[u],low[e]);
        }
        else if(inst[e])
            low[u]=min(low[u],dfn[e]);
    }
    if(low[u]==dfn[u])
    {
        scc++;
        while(1)
        {
            int x=st[s--];
            inst[x]=0;
            sct[x]=scc;
            if(x==u) break;
        }
    }
}
void To_order()
{
    int z=0;
    queue<int>q;
    for(int i=1;i<=scc;i++)
        if(!in[i]) q.push(i);
    while(!q.empty())
    {

        int u=q.front();q.pop();
        if(z<m-1) res[u]=z++;
        else res[u]=z;
        for(int i=head1[u];~i;i=edge1[i].next)
        {
            int e=edge1[i].e;
            in[e]--;
            if(!in[e]) q.push(e);
        }
    }
    printf("YES\n");
    for(int i=1;i<=n;i++)
    {
        char ch=res[sct[i]]+'a';
        printf("%c",ch);
    }
    printf("\n");
}
ll a[maxn];
ll b[maxn];
int main()
{
    memset(head,-1,sizeof(head));
    memset(head1,-1,sizeof(head1));
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
    for(int i=1;i<=n-1;i++){
        addedge(a[i],a[i+1]);
        addedge(b[i],b[i+1]);
    }
    for(int i=1;i<=n;i++) if(!dfn[i])
        Tarjan(i);
    for(int i=1;i<=n;i++)
    {
        for(int k=head[i];~k;k=edge[k].next)
        {
            int e=edge[k].e;
            if(sct[i]!=sct[e]){
                addedge1(sct[i],sct[e]);
                in[sct[e]]++;
            }
        }
    }
    if(m>scc) printf("NO\n");
    else To_order();
}
/***
样例测试空间:
6
5
1 2
2 3
3 1
3 5
2 6
***/

同样例题:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只酷酷光儿( CoolGuang)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值