1. 程式人生 > >2017.10.6 國慶清北 D6T1 排序

2017.10.6 國慶清北 D6T1 排序

技術分享 輸出 hide clas splay tro algo digi src

題目描述

小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

2017.10.6 國慶清北 D6T1 排序