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 }
以上是关于2017.10.6 国庆清北 D6T1 排序的主要内容,如果未能解决你的问题,请参考以下文章