CodeForces 451B
#include<iostream> #include<algorithm> #include<cstring> using namespace std; int n; struct Node { int x,id; }p[100010]; bool cmp(Node x,Node y) { return x.x<y.x; } int main() { int l = -1,r; bool flag = true; cin >> n; for(int i=1;i<=n;i++) { cin >> p[i].x; p[i].id=i; } sort(p+1,p+n+1,cmp); p[n+1].id = -1; for(int i =1; i<=n;i++) { if(p[i].id!= i) { l=i; break; } } if(l == -1){ cout<< "yes" <<endl<< "1 1"<< endl; return 0; } for(int i =l;i <= n;i++) { if(p[i].id- p[i+1].id!= 1) { r=i; break; } } for(int i=r+1;i<= n;i++) { if(p[i].id != i) { flag=false; break; } } if(flag){ cout<< "yes" << endl<< l<<" "<<r<<endl; } else cout<<"no" << endl; return 0; }
陶叔的讲解,我的代码!
题意:给你一个长度不超过10^5的数组,数组中的每个元素互不相同。
•问是否能翻转数组的某个区间,使得数组形成一个有序的升序序列。
•先按数组元素值的大小排序
•排完序之后,就能形成一个序列id[i]
•id[i]表示第i个数字在数组中的大小排名第几
•比如说:
•a[1]=1,a[2]=10,a[3]=6,a[4]=2,a[5]=11
•id[1]=1,id[2]=4,id[3]=3,id[4]=2,id[5]=5
•a[1]=1,a[2]=10,a[3]=6,a[4]=2,a[5]=11
•id[1]=1,id[2]=4,id[3]=3,id[4]=2,id[5]=5
•于是我们发现,如果我们能将id区间的某一段翻转过后,使得id[i]=i,那么就可以找到满足题意的区间
•找左端点L:第一个id[i]不等于i的端点
•找右端点R:第一个id[i]-id[i+1]不等于1的端点
•接下来我们需要验证剩余的i>R,id[i]是否等于i