580 div2 C题解

题目描述
You are given integer n. You have to arrange numbers from 1 to 2n, using each of them exactly once, on the circle, so that the following condition would be satisfied:

For every n consecutive numbers on the circle write their sum on the blackboard. Then any two of written on the blackboard 2n numbers differ not more than by 1.

For example, choose n=3. On the left you can see an example of a valid arrangement: 1+4+5=10, 4+5+2=11, 5+2+3=10, 2+3+6=11, 3+6+1=10, 6+1+4=11, any two numbers differ by at most 1. On the right you can see an invalid arrangement: for example, 5+1+6=12, and 3+2+4=9, 9 and 12 differ more than by 1.

在这里插入图片描述示意图:左侧为正确的环,右侧为不满足条件的环

Input
The first and the only line contain one integer n (1≤n≤105).

Output
If there is no solution, output “NO” in the first line.

If there is a solution, output “YES” in the first line. In the second line output 2n numbers — numbers from 1 to 2n in the order they will stay in the circle. Each number should appear only once. If there are several solutions, you can output any of them.

题意
给了一个数n,要求将1-2n个数围城一个环,使得任意连续相连的n个数的和的差值不超过1,如果存在则输出这个环

题解
咋一看,立马想到当时做素数环的时候,想到应该dfs一下,但是感觉太麻烦,以C题来说,一般没有这么复杂,所以先大胆猜想一下
首先,因为是2*n,所以不难发现,如果n是偶数,那么环总是可以被分成两半,而且不可能任何时候左半边都等于右半边,所以显然如果n是偶数,那么必定无法形成环
那么,如果n是奇数的话,那么应该是可以形成的,我们可以推断一下。
首先,当n取1,那么显然就是1 2
当n取3,题目给了1 4 5 2 3 6(这个就很容易发现,1和2显然是应该处在一个对立的位置上,假设1是第一个,那么2一定是第n个,不然差值就会大于1)
然后可以发现,4 5, 2 3都是连着出现的,而这六个数已经形成了一个正确的环,那么如果数字变为5,我们可以根据3的六个数字,继续推算出剩下的四个数字位置(因为上面六个数已经满足条件了,我们根据推断又不难发现奇数都应该是满足条件的,那么我们将一个局部正确的环进行延伸,应该可以得到一个正确的拓展的环,所以不妨继续拓展一下)
那么 5的序列应该是1 4 5 8 9 2 3 6 7 10
至此,我们可以发现规律了,1后面的几个数的位置应该是固定的,而2后面几个数的位置也应该是固定的,每次都是上一次的延伸,那么不妨可以直接写出该数列,那么这个推断的数列就是答案了

#include <bits/stdc++.h>
using namespace std;
int a[200005];
int b[200005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,i,j,k;
    long long t;
    bool flag=0;
    cin>>n;
    if(n==1){
        cout<<"YES"<<endl;
        cout<<1<<" "<<2<<endl;//将1特判一下(其实也没有必要)
    }
    else if(n%2==0){
        cout<<"NO"<<endl;//(偶数是必定不可以的)
    }
    else{
            a[1]=1;
        for(i=2;i<=2*n;i++){//(利用标记数组b来实现值的改变,因为是不断差3和不断加1的关系,在2处发生了改变)
            if(b[i-1]==0){
            if(a[i-1]!=2*n-1){
                a[i]=a[i-1]+3;
                //cout<<a[i]<<endl;
                b[i]=1;
            }
            else if(a[i-1]==2*n-1){
                a[i]=2;
                b[i]=1;
            }
            }
            if(b[i-1]==1){
                a[i]=a[i-1]+1;
                b[i]=0;
            }
        }
        //for(i=1;i<=2*n;i++)
          //  cout<<a[i]<<" ";
            cout<<"YES"<<endl;
            for(i=1;i<=2*n;i++)
                cout<<a[i]<<" ";
    }
    return 0;
}

所以不需要dfs就可以解决这个问题了
错误原因:看错题了!!!以为是连续三个数,结果一直wa,改了两个字母就ac了,错失了上分的良机…

加油

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值