CF653C Solution
题解
下文将不符合条件的序列元素称为“劣元素”。
可以发现,交换两数\(t_i,t_j\)最多只可影响到\(\{t_{i-1},t_i,t_{i+1},t_{j-1},t_j,t_{j+1}\}6\)个序列中元素。因此我们可以找出所有劣元素,如果其个数\(>6\)则判断无法实现。
因为\(t_{2k+1}>t_{2k}\)或\(t_{2k+1}>t_{2k+2}\)此类劣元素一定是成对出现且互相影响的,只有将劣元素与其他元素互换才会对序列状态产生影响。因此我们可以枚举劣元素与其他元素,将其互换后判断当前序列是否合法。因为经过先前特判劣元素个数\(\le 6\),而判断序列是否合法只需判断所有劣元素与互换的元素是否合法即可,时间复杂度为\(O(36n)\)。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=15e4+10,inf=0x3f3f3f3f;
int t[N],wr[N];//wr:劣元素
bool w[N];//w[i]:下标为i的元素是/否(1/0)为劣元素
bool check(int x)//下标为x的元素是否合法
{return (x%2 && t[x]<t[x-1] && t[x]<t[x+1]) || (x%2==0 && t[x]>t[x-1] && t[x]>t[x+1]);}
int main()
{
int n,cnt=0,ans=0;//cnt:劣元素个数
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&t[i]);
t[0]=inf;
//为使t[1]可以被check判断合法,需保证t[0]>a[1]
if(n%2) t[n+1]=inf;
//为使t[n]可以被check判断合法,需保证当n为偶数时t[n+1]<t[n],奇数时t[n+1]>t[n]
for(int i=1;i<=n;i++)
if(!check(i)) {wr[++cnt]=i; w[i]=1;}
if(cnt>6) {printf("0"); return 0;}
for(int i=1;i<=cnt;i++)
{
for(int j=1;j<=n;j++)
{
if(w[j] && j<=wr[i]) continue;
swap(t[wr[i]],t[j]);
bool flag=check(j);
for(int k=1;k<=cnt;k++) flag&=check(wr[k]);
swap(t[wr[i]],t[j]); ans+=flag;
//为使接下来的判断不受影响,需抹消互换操作
}
}
printf("%d",ans);
return 0;
}