2018年四校联合周赛-第三场 A-Fill的序列

题目链接:http://www.fjutacm.com/Problem.jsp?pid=3272

对于第i个数如果不满足条件,则记录一下不满足条件的数量:

如果cnt>4,因为你的交换最多影响4组,所以肯定无解

如果cnt=4,错误位置wa1,wa2,wa3,wa4必须满足wa2-wa1=1且wa4-wa3=1,这个时候可以尝试交换wa2和wa4

如果cnt=3,则wa2-wa1=1或者wa3-wa2=1才可以考虑交换

如果cnt=2,分wa1和wa2是否相邻来考虑交换

如果cnt=1,则考虑与wa1或者wa1后面一个数交换

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<time.h>
#include<cctype>
#define INF 0x3f3f3f3f
#define EXP 0.00000000001
#define MOD 1000000007
#define MAXN 100005
#define PI acos(-1.0)
#define ltree 2*id,ll,mid
#define rtree 2*id+1,mid+1,rr
#define mem(a) memset(a,0,sizeof(a))
typedef long long LL;


using namespace std;


int a[150005];
int ans=0;
int wa[10];


bool solve(int p1,int p2)
{
    if(p1&1&&p2&1)
        return a[p1]<a[p1+1]&&a[p1]<a[p1-1]&&a[p2]<a[p2-1]&&a[p2]<a[p2+1];
    else if(p1&1&&p2%2==0)
        return a[p1]<a[p1+1]&&a[p1]<a[p1-1]&&a[p2]>a[p2+1]&&a[p2]>a[p2-1];
    else if(p1%2==0&&p2&1)
        return a[p1]>a[p1+1]&&a[p1]>a[p1-1]&&a[p2]<a[p2+1]&&a[p2]<a[p2-1];
    else
        return a[p2]>a[p2+1]&&a[p2]>a[p2-1]&&a[p1]>a[p1+1]&&a[p1]>a[p1-1];
}


void get(int p1,int p2)
{
    swap(a[p1],a[p2]);
    ans+=solve(p1,p2);
    swap(a[p1],a[p2]);
}


int main()
{
	int n;
	scanf("%d",&n);
	a[0]=INF;
	for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    if(n&1)
        a[n+1]=INF;
    else
        a[n+1]=0;
    int cnt=0;
    for(int i=1;i<n;++i)
    {
        if(cnt>=5)
            break;
        if(i&1&&a[i]>=a[i+1])
            wa[++cnt]=i;
        else if(!(i&1)&&a[i]<=a[i+1])
            wa[++cnt]=i;
    }
    if(cnt==4)
    {
        if(wa[2]-wa[1]==1&&wa[4]-wa[3]==1)
            get(wa[2],wa[4]);
    }
    else if(cnt==3)
    {
        if(wa[2]-wa[1]==1)
        {
            get(wa[2],wa[3]);
            get(wa[2],wa[3]+1);
        }
        if(wa[3]-wa[2]==1)
        {
            get(wa[1],wa[3]);
            get(wa[1]+1,wa[3]);
        }
    }
    else if(cnt==2)
    {
        get(wa[1],wa[2]);
        get(wa[1],wa[2]+1);
        get(wa[1]+1,wa[2]);
        get(wa[1]+1,wa[2]+1);
        if(wa[2]-wa[1]==1)
        {
            for(int i=1;i<=n;++i)
            {
                if(i==wa[1]||i==wa[2]||i==wa[2]+1)
                    continue;
                get(i,wa[2]);
            }
        }
    }
    else if(cnt==1)
    {
        for(int i=1;i<=n;i++)
        {
            if(i==wa[1]||i==wa[1]+1)
                continue;
            get(i,wa[1]);
            get(i,wa[1]+1);
        }
        get(wa[1],wa[1]+1);
    }
    printf("%d\n",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值