2017.10.6 国庆清北 D6T1 排序
题目描述
小Z 有一个数字序列a1; a2; .... ; an,长度为n,小Z 只有一个操作:选
定p(1<p<n),然后把ap 从序列中拿出,然后再插⼊到序列中任意位置。
比如a 序列为1,2,4,5,3,p = 5,可以取出3,然后在任意位置插入,可
以变为1,2,3,4,5。
现在给你一个序列a,问你是否可以通过一次操作把整个序列从小到大
排好序(变成不降的)。
输入输出格式
输入格式:
第一行一个整数n,第二行空格隔开的n 个整数,代表a 序列。
输出格式:
如果可以n次操作可以排好序,输出”YES”,否则输出”NO”。
输入输出样例
输入样例#1:
5 1 2 4 5 3
输出样例#1:
YES
说明
对于30% 的数据,满足n <=1000。
对于60% 的数据,满足n <=10^5。
对于100% 的数据,满足n <=10^6; 1 <=ai <=10^6。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 要使序列不降,那么就要让序列中比前边的数小的那些数移动到正确的位置。因为只能移动一个数,所以序列中只能存在一个数比前边的数字小。 所以求一下最长不降子序列的长度len,如果n-len<=1,及不用移动(把这个数取出来再插回去)或者移动一个数就能使序列不降,那么输出YES,否则输出NO。 3 4 因为数据范围到10^6,所以要用O(nlogn)方法做的做。 5 */ 6 7 8 #include<iostream> 9 #include<cstdio> 10 #include<cmath> 11 #include<algorithm> 12 #include<cstring> 13 #define N 1000005 14 using namespace std; 15 16 int n,sum,len; 17 int a[N],num[N]; 18 19 inline void read(int &num) 20 { 21 register char c=getchar(); 22 for(;!isdigit(c);c=getchar()); 23 for(;isdigit(c);c=getchar()){num=num*10+c-'0';} 24 } 25 26 void init() 27 { 28 read(n); 29 for(int i=1;i<=n;++i) 30 { 31 read(a[i]); 32 } 33 if(n==0||n==1) 34 { 35 puts("YES"); 36 return; 37 } 38 len=1,num[1]=a[1]; 39 for(int i=2;i<=n;i++) 40 { 41 if(a[i]>=num[len]) num[++len]=a[i]; 42 else 43 { 44 int j=upper_bound(num+1,num+len+1,a[i])-num; 45 num[j]=a[i]; 46 } 47 } 48 if(n-len<=1) printf("YES"); 49 else printf("NO"); 50 } 51 52 int main() 53 { 54 freopen("sort.in","r",stdin); 55 freopen("sort.out","w",stdout); 56 init(); 57 return 0; 58 }