codeforces 286(Round #176)题解

A:水题,我的做法是算2×2格子的和,不为2即可

B:水题,贪心+二分查找

C:我是手写几个数的表,看的规律,很容易发现,前两个后两个可以分为一组,第一个是2,第二个是n,倒数第二个是1,倒数第一个是n-1...以此类推,注意可以用stl的next_permutation函数枚举,方便看规律。具体证明没推,cf貌似有。

上代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=100005;
int a[N];
int main()
{
       int i,n;
       scanf("%d",&n);
       if(!(n%4==0) && !(n%4==1)) {printf("-1");return 0;} 
       if(n%4==0)
       { 
         int h=2;
         int t=n;
         for(i=1;i<=n/2;++i)
         {
            if(i%2==1) 
            {
                    a[i]=h;
                    a[n-i]=h-1;
                    h=h+2;;
            }
            if(i%2==0)
            {
                     a[i]=t;
                     a[n-i+2]=t-1;
                     t=t-2;
            }
         }
       }
       else if(n%4==1)
       {
          int h=2;
         int t=n;
         for(i=1;i<=n/2;++i)
         {
            if(i%2==1) 
            {
                    a[i]=h;
                    a[n-i]=h-1;
                    h=h+2;;
            }
            if(i%2==0)
            {
                     a[i]=t;
                     a[n-i+2]=t-1;
                     t=t-2;
            }
         }
         a[n/2+1]=(n+1)/2;
       } 
       for(i=1;i<=n;++i)
        printf("%d ",a[i]);
       return 0;
}

D:其实不用想的太复杂,枚举即可。这里用到了deque双端队列,实现起来较为方便,每次把分组的最后一组的第一个加到队尾,然后每组第一个移到后面一组第一个位置处,然后将队头删除即可

#include<iostream>//deque
#include<algorithm>
#include<cstdio>
#include<deque>
using namespace std;
deque<int> d;
int main()
{
    int i,n;
    scanf("%d",&n);
    for(i=1;i<=n;++i)
     d.push_back(i);
    for(i=2;i<=n;++i)
    {
      int l=(n-1)/i*i;
      d.push_back(d[l]);
      while(l)
      {
        d[l]=d[l-i];
        l=l-i;
      }
      d.pop_front();
    } 
    for(i=0;i<n;++i)
     printf("%d ",d[i]);
    return 0; 
}

E:不错的题,类似于匹配括号,这里用到了栈,因为右面要是负数,显然从右往左扫比较方便。将需要匹配的位置加入栈中,依次匹配即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1000005;
int a[N],b[N],st[N];
int main()
{
     int x;
     int i,n,t;
     scanf("%d",&n);
     if(n%2==1) {printf("NO");return 0;}
     for(i=1;i<=n;++i)
       scanf("%d",&a[i]);
     scanf("%d",&t);
     for(i=1;i<=t;++i)
     {
        scanf("%d",&x);
        b[x]=1;
     }
     int now=0;
     for(i=n;i>=1;--i)
     {
       if(!b[i] && (now && a[i]==a[st[now]])) a[st[now--]]=-a[i];
       else st[++now]=i;
     } 
     //从右至左匹配,将右面变成负数 
     if(now==0) 
     {
          printf("YES\n");
          for(i=1;i<=n;++i)
           printf("%d ",a[i]);
     }
     else printf("NO\n");
     return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值