Repetitions Decoding(Codeforces Round #773(Div. 2))

传送门

题目大意

定义一个串联重复序列:一个长度为偶数的序列串联重复当且仅当它的前一半和后一半每个对应位置上的元素都相等。有\(t\)个询问,每次给你一个长度为\(n(n为偶数)\)的串,现你可以做若干次操作,每次操作可以取某个在串中的元素\(c\)并且在某个位置插入长度为\(2\)的串\(“cc”\),问能否构造出一个方案使得最后能把操作之后的串分成若干段,且每一段都是串联重复的。若不行,则输出\(-1\);不然,先输出操作数,之后每行输出每次操作的位置和元素,再输出串联重复序列的个数,最后一行输出每一段串联重复序列的长度。\((1\leq t\leq30000,1\leq n\leq500,1\leq a_i\leq10^9,\sum n^2\leq250000)\)

思路

赛时还以为是一道什么算法题,想了好久不会做。赛后看了大佬的代码的时候发现这道题其实就是一道简单构造题,哭死。具体是这样的,我们可以一部分一部分构造,先找到第一个与还未构造段的开头相等的元素的位置,然后以这一段为模型构造出后面半段;如果找不到,就可以直接输出\(-1\)

代码

#include<bits/stdc++.h>
using namespace std;
int a[505];
int x[1000005],y[1000005],z[1000005];
int main()
{
    int _;
    scanf("%d",&_);
    while(_--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        bool ck=0;
        int xx=0,yy=1,zz=0;
        for(int i=1;i<=n;i+=2)
        {
            int r=-1;
            for(int j=i+1;j<=n;j++)
            {
                if(a[i]==a[j]){r=j;break;}
            }
            if(!(~r)){ck=1;break;}
            for(int j=i+1;j<r;j++)
            {
                x[++xx]=yy+j+r-i-i-1;
                y[xx]=a[j];
            }
            z[++zz]=(r-i)<<1;
            yy+=z[zz];
            int l=i+1;
            while(l<r)swap(a[l],a[r]),l++,r--;
        }
        if(ck){printf("-1\n");continue;}
        printf("%d\n",xx);
        for(int i=1;i<=xx;i++)printf("%d %d\n",x[i],y[i]);
        printf("%d\n",zz);
        for(int i=1;i<=zz;i++)printf("%d ",z[i]);
        printf("\n");
    }
    return 0;
}
posted @ 2022-02-24 13:57  Jerry_Black  阅读(134)  评论(0)    收藏  举报