AtCoder Regular Contest 102F Revenge of BBuBBBlesort! 乱搞

38 篇文章 0 订阅
36 篇文章 0 订阅

Description


给一个n排列p[],若存在一个位置i使得p[i-1]>p[i]>p[i+1],那么就可以交换p[i-1]和p[i+1]

Solution


真·感性乱搞+分类讨论

首先记a[i]=[p[i]=i],那么我们可以把p分成若干段01交替出现、首尾皆为0的子串。由交换性质可知这些段之间互不影响,即交换不会跨过这些段

考虑一整段[l,r]什么情况会No。
如果出现了最大值大于r或最小值小于l肯定不行,因为我们不能把它交换出去。
由于每次交换的两个位置奇偶性相同,那么每个位置上的数字也要和下标奇偶性相同。这个好像比较显然
还有就是,我们不会让一个数字先往左换、再往右换,并且方向相同的两个数相对位置不会改变。由交换性质可知数字的交换方向一定是单向的,而相对位置改变意味着某个数反向交换了

于是瞎搞就可以了,每个位置只会访问一次所以是O(n)的

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>

#define rep(i,st,ed) for (int i=st;i<=ed;++i)

const int INF=0x3f3f3f3f;
const int N=2000005;

int a[N];

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

bool check(int l,int r) {
	int mx=0,mn=INF;
	rep(i,l,r) {
		mx=std:: max(mx,a[i]);
		mn=std:: min(mn,a[i]);
	}
	if (mn<l||mx>r) return true;
	int r1=0,r2=0;
	rep(i,l,r) if (a[i]!=i) {
		if (a[i]<i) {
			if (r1<a[i]) r1=a[i];
			else return true;
		} else {
			if (r2<a[i]) r2=a[i];
			else return true;
		}
	}
	return false;
}

int main(void) {
	int n=read(),x;
	rep(i,1,n) a[i]=read();
	rep(i,1,n) if (a[i]!=i) {
		for (x=i;a[x+1]==x+1&&a[x+2]!=x+2;) x+=2;
		x=std:: min(x,n);
		if (check(i,x)) return puts("No"),0;
		i=x;
	}
	return puts("Yes"),0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值