zoukankan      html  css  js  c++  java
  • 【agc001d】Arrays and Palindrome

    Portal -->agc001D

    Description

      给你一个(m)个数的排列(A),这个(A)中元素的顺序可以随便调换,(A)中的元素的和为(n),现在要你构造一个数组(B)(长度为(m1)),满足:如果一个字符串同时满足:

    1、头(A_1)个字符,接下来的(A_2)个字符,接下来的(A_3)个字符...接下来的(A_m)个字符分别构成回文串

    2、头(B_1)个字符,接下来的(B_2)个字符,接下来的(B_3)个字符...接下来的(B_{m1})个字符分别构成回文串

      那么这个字符串中每一个位置上的字符都一样

      

    Solution

      日常不会构造题。。。qwq

      

      有一个比较好的想法就是。。画蚊香。。大概是这样:

    ​  这个图对应的是(A={3,2})(B={4,1})

    ​  然后我们要做的就是。。使得连完线之后可以一笔画

    ​  然后发现如果说出现一个长度为奇数的回文串,最中间的那个点就会没有线连,然后为了让它和其他的点连上,这个点的度数必须是(1),然后为了保证一笔画,这样的点必须至多出现两个,所以奇数长度的回文串至多只能有两个,否则就无解了,然后多画几组会发现。。如果出现奇数长度的回文串它们还必须出现在一头一尾qwq

    ​  那么剩下的就是构造啦

      当全部都是偶数的时候,我们在最开头先放一个(1),这样后面就错开了,然后第(1)(m-1)都可以直接复制下来,至于最后一个回文串,我们可以放一堆(2)中间夹一个(1)这样(具体自己画一下就知道了)

      当有一个奇数的时候,我们把它放在(A)的最后,(B)的前面部分的构造方式同上,最后一个长度为奇数的回文串就简单一些,直接全部上(2)就好了

      当有两个奇数的时候,我们将其放在一头一尾,然后(B)的第一个元素设成(A_1+1),这样后面的情况就和只有一个奇数、并且已经放了一个(1)的情况一样了,剩下的构造同上

      

      代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1e5+10;
    int a[N],b[N*2],lis[3];
    int n,m,cnt;
    bool firstcheck(){
    	int cnt=0;
    	for (int i=1;i<=n;++i)
    		cnt+=a[i]&1;
    	return cnt<=2;
    }
    void get_b(){
    	int sum;
    	if (cnt==0){
    		b[++b[0]]=1; sum=m-1;
    		for (int i=1;i<n;++i) b[++b[0]]=a[i],sum-=a[i];
    		if (sum==0) return;
    		sum-=1; sum/=2;
    		for (int i=1;i<=sum/2;++i) b[++b[0]]=2;
    		b[++b[0]]=1;
    		for (int i=sum/2+1;i<=sum;++i) b[++b[0]]=2;
    	}
    	else if (cnt==1){
    		b[++b[0]]=1;
    		for (int i=1;i<n;++i) b[++b[0]]=a[i];
    		for (int i=1;i<=(a[n]-1)/2;++i) b[++b[0]]=2;
    	}
    	else{
    		b[++b[0]]=a[1]+1;
    		for (int i=2;i<n;++i) b[++b[0]]=a[i];
    		for (int i=1;i<=(a[n]-1)/2;++i) b[++b[0]]=2;
    	}
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	scanf("%d%d",&m,&n);
    	for (int i=1;i<=n;++i) scanf("%d",a+i);
    	if (!firstcheck()){printf("Impossible
    "); return 0;}
    	cnt=0;
    	for (int i=1;i<=n;++i){
    		if ((a[i]&1)) 
    			lis[++cnt]=i;
    	}
    	if (lis[1]) swap(a[n],a[lis[1]]);
    	if (lis[2]) swap(a[1],a[lis[2]]);
    	for (int i=1;i<=n;++i) printf("%d ",a[i]); printf("
    ");
    
    	get_b();
    	printf("%d
    ",b[0]);
    	for (int i=1;i<=b[0];++i) printf("%d ",b[i]); printf("
    ");
    }
    
  • 相关阅读:
    LeetCode Subsets II
    LeetCode Rotate Image
    LeetCode Palidrome Number
    LeetCode Generate Parentheses
    LeetCode Maximum Subarray
    LeetCode Set Matrix Zeroes
    LeetCode Remove Nth Node From End of List
    Linux Loop设备 使用
    Linux 文件系统大小调整
    LeetCode N-Queens II
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9860401.html
Copyright © 2011-2022 走看看