分析:
肥肠考验分析能力的一道题目
将操作反过来看,初始状态下ai=iai=i的一个序列,要求对任意满足ap−1<ap<ap+1ap−1<ap<ap+1的三元组,都可以翻转,求最终能否转移成给出的序列。
首先有个很显然的性质,如果以ii为中心做了一次翻转,那么永远不可能再以为中心做一次翻转。换言之,aiai的值就永远不能改变。
证明应该很显然,因为在ii处做了一次翻转,所以翻转后,如果在i−1i−1处做翻转,则要求ai>ai−1ai>ai−1,在这里并不满足,因此要么改变aiai,要么改变ai−1ai−1。因为能改变aiai的只有在i−1i−1或i+1i+1位置翻转,因此只能尝试改变ai−1ai−1的值,但如果ai−1ai−1被改了,那么ai−2>ai−1ai−2>ai−1,所以在i−1i−1位置不能反转。i+1i+1位置同理。
有了这个性质,那么问题就很容易了。
可以尝试把原序列分成若干小段[l,r][l,r],每一段对于l+1,l+3,l+5……r−1l+1,l+3,l+5……r−1位置,满足条件ai=iai=i,对于另外的位置,满足ai≠iai≠i。方便起见,把第一类点称为不动点,第二类点称为动点。
现在继续分析性质,这次从值的角度出发,对于任意一个值xx,其初始位置在一个动点上,其必然满足:它如果第一步是向左转移,那么它永远不会向右走,反之亦然(即如果第一步向右转移,那么永远不会向左走)。证明很容易,如果它向左转移了,那么设初始位置为,那么转移后满足ai<ai−1<xai<ai−1<x,如果它要向右转移,则必须令ai−1>xai−1>x,然而ai−1ai−1是不动点,所以这永远无法满足。
并且,任意两个向左转移的元素,其相对位置不会发生变化,原因很简单,如果要发生变化,则一定交换了这两个元素,然而一旦交换,则有一个会向右转移,不合法。向右转移的元素同理。
现在总结一下性质:
首先对给出的序列分段,每一段要求al+1=l+1,al+3=l+3……ar−1=r−1al+1=l+1,al+3=l+3……ar−1=r−1
同时al≠l,al+2≠l+2……ar≠ral≠l,al+2≠l+2……ar≠r
a[l,r]a[l,r]中所有值都在[l,r][l,r]这个区间内。
并且,所有i<aii<ai的元素严格递增,所有i>aii>ai的元素也严格递增。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 300010
#define INF 0x3FFFFFFF
using namespace std;
int n;
int a[MAXN];
bool used[MAXN];
bool check(int l,int r){
if(l>r)
return 0;
if(l==r)
return a[l]!=l;
int minv=INF;
int maxv=0;
for(int i=l;i<=r;i++){
minv=min(minv,a[i]);
maxv=max(maxv,a[i]);
}
if(minv!=l||maxv!=r)
return 1;
for(int i=l+1;i<=r;i+=2)
if(a[i]!=i)
return 1;
for(int i=l;i<=r;i+=2)
if(a[i]==i)
return 1;
int lasx=0,lasy=0;
for(int i=l;i<=r;i+=2){
if(i<a[i]){
if(a[i]<lasx)
return 1;
lasx=a[i];
}
if(i>a[i]){
if(a[i]<lasy)
return 1;
lasy=a[i];
}
}
return 0;
}
int main(){
SF("%d",&n);
for(int i=1;i<=n;i++)
SF("%d",&a[i]);
for(int i=1;i<=n;i++)
used[i]=(a[i]==i);
int las=1;
used[0]=1;
for(int i=1;i<=n;i++){
if(used[i]==1&&used[i-1]==1){
if(check(las,i-2)){
PF("No");
return 0;
}
las=i+1;
}
else if(used[i]==1&&used[i-2]==1)
continue;
else if(used[i]==1&&used[i-3]==1){
if(check(las,i-2)){
PF("No");
return 0;
}
las=i-1;
}
else if(used[i]==1){
PF("No");
return 0;
}
}
if(check(las,n))
PF("No");
else
PF("Yes");
}