2017.10.6 国庆清北 D6T1 排序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 emmmmmm...这也是我第一次写O(nlogn)的求最长不降子序列,毕竟比较lowbit。
 6 */
 7 
 8 
 9 #include<iostream>
10 #include<cstdio>
11 #include<cmath>
12 #include<algorithm>
13 #include<cstring>
14 #define N 1000005
15 using namespace std;
16 
17 int n,sum,len;
18 int a[N],num[N];
19 
20 inline void read(int &num)
21 {
22     register char c=getchar();
23     for(;!isdigit(c);c=getchar());
24     for(;isdigit(c);c=getchar()){num=num*10+c-0;};
25 }
26 
27 void init()
28 {
29     read(n);
30     for(int i=1;i<=n;++i)
31     {
32         read(a[i]);
33     }
34     if(n==0||n==1)
35     {
36         puts("YES");
37         return;
38     }
39     len=1,num[1]=a[1];
40     for(int i=2;i<=n;i++)
41     {
42         if(a[i]>=num[len]) num[++len]=a[i];
43         else
44         {
45             int j=upper_bound(num+1,num+len+1,a[i])-num;
46             num[j]=a[i];
47         }
48     }
49     if(n-len<=1) printf("YES");
50     else printf("NO");
51 }
52 
53 int main()
54 {
55     freopen("sort.in","r",stdin);
56     freopen("sort.out","w",stdout);
57     init();
58     return 0;
59 }
View Code





以上是关于2017.10.6 国庆清北 D6T1 排序的主要内容,如果未能解决你的问题,请参考以下文章

2017.10.6 国庆清北 D6T2 同余方程组

2017.10.6 国庆清北 D6T2 同余方程组

清北学堂模拟赛d6t1 角谷猜想

清北学堂国庆day6解题报告

清北学堂国庆day5解题报告

2017-10-6 清北刷题冲刺班p.m