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。

 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 }
View Code
原文地址:https://www.cnblogs.com/lovewhy/p/7652389.html