[AGC001D]Arrays and Palindrome-并查集-构造

Arrays and Palindrome

Problem Statement

Snuke got a present from his mother on his birthday. The present was a pair of two sequences a and b, consisting of positive integers. They satisfied all of the following properties:

The sum of all elements of a is N.
The sum of all elements of b is N.
Any string of length N that satisfies the following two conditions (1) and (2) will also satisfy the condition (3).
(1) Any of the following forms a palindrome: the first a1 letters, the following a2 letters, the following a3 letters and so on.
(2) Any of the following forms a palindrome: the first b1 letters, the following b2 letters, the following b3 letters and so on.
(3) All N letters are the same.
He was happy, until one day he lost both of the sequences. Now, he only remembers that the sequence a was a permutation of another sequence A of length M.

To bring him happiness again, his mother has decided to give him another pair of sequences a and b that satisfies his favorite properties and is consistent with his memory.

Constraints

1≦N≦105
1≦M≦100
1≦Ai≦105

The sum of all Ai equals N.

Input

The input is given from Standard Input in the following format:

N M
A1 A2 … AM

Output

If there exists a pair of sequences a and b that satisfies the properties and is consistent with Snuke’s memory, print three lines. The first line must contain the sequence a, the second line must contain the length of the sequence b, and the third line must contain the sequence b.

If such a pair does not exist (because Snuke’s memory is wrong or some other reason), print a single line containing the word Impossible (case-sensitive).

Sample Input 1

3 2
2 1

Sample Output 1

1 2
1
3

Sample Input 2

6 1
6

Sample Output 2

6
3
1 2 3

Sample Input 3

55 10
1 2 3 4 5 6 7 8 9 10

Sample Output 3

Impossible

咱至今都记得在同学出的NOIP模拟赛中被这题狂虐花掉整整1h才A的快感……
做完以后看着奇短无比的代码整个人都是蒙圈的……


题意:
给出一个数字之和为N的顺序可变的 a 数组,构造一个数字和为N的 b 数组,满足对于任意满足前两个条件的字符串,一定满足第三个条件:
1.从头开始的 a1 个字符, a1 个后紧接着的 a2 个、 a3 个……分别为回文串。
2.从头开始的 b1 个字符, b1 个后紧接着的 b2 个、 b3 个……分别为回文串。
3.该字符串仅由同一字符构成。

思路:
画蚊香。(咱和同学都喜欢这么叫)
上图你们就知道什么意思了。
[AGC001D]Arrays and Palindrome-并查集-构造_第1张图片
鼠绘太丑不要在意。
假设红线是 a 数组,黄线是 b 数组。
那么上图的 a 数组内容为: {5,3} b 数组为 {4,4}
可以发现,可利用的回文关系可以很轻松画成上面的蚊香型图。
根据并查集思想,如果整张图能一笔画,那么就是有解。

那么接下来呢?
多画几张这样的蚊香图,可以发现,长度为奇数的回文串很没有前途。
有多没有前途呢?
没有前途到只能放在队首或队尾,超过两个就无解了。

那么无解的情况完成了,接下来就是构造 b 和给出 a 的顺序了。
可以考虑这么构造:
a 里的奇数丢到最前和最后,挑选其中一个令其匹配的b值等于它的长减1,另一个的b值等于它本身加1,其他的偶数项一一对应上 a 排列即可。
相当于这样:

3 2 4 6 4 2 3
4 2 4 6 4 2 2

很明显中间的相对的 a b 可以构成有一个向外的 b 接口和一个 a 接口的联通形式
前端和后端构成了仅有 b 接口和 a 接口中的一个的形态,刚好满足条件。

那么就做完了~
特殊情况记得特判即可。
(考试时写的代码有点奇怪不要在意)

#include
#include
#include
#include
#include

using namespace std;

inline int read()
{
    int x=0;char ch=getchar();
    while(ch<'0' || '9'while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
    return x;
}

const int M=1e5+9;

int m;
int a[M],b[M],top;

int main()
{
    int n=read(),m=read();
    int odd1=-1,odd2=-1;
    for(int i=1;i<=m;i++)
    {
        a[i]=read();
        if(a[i]&1)
        {
            if(odd1==-1)
                odd1=i;
            else if(odd2==-1)
                odd2=i;
            else
            {
                puts("Impossible");
                return 0;
            }
        }
    }

    if(m==1)
    {
        if(a[1]==1)
            printf("1\n1\n1\n");
        else
            printf("%d\n2\n1 %d\n",a[1],a[1]-1);
        return 0;
    }

    if(odd1!=-1)
        swap(a[1],a[odd1]);
    if(odd2!=-1)
        swap(a[m],a[odd2]);

    for(int i=1;i<=m;i++)
        printf("%d%c",a[i]," \n"[i==m]);

    if(a[m]==1)
    {
        printf("%d\n",m-1);
        printf("%d ",a[1]+1);
        for(int i=2;iprintf("%d ",a[i]);
        puts("");
        return 0;
    }

    b[1]=a[1]+1;
    for(int i=2;i1;

    printf("%d\n",m);
    for(int i=1;i<=m;i++)
        printf("%d%c",b[i]," \n"[i==m]);

    return 0;
}

你可能感兴趣的:(并查集【Disjoint,set,union】)