2020.06.26日常總結

UVA11039 Building Designing\color{green}{\texttt{UVA11039 Building Designing}}

[Problem]\color{blue}{\texttt{[Problem]}}

  • nn 個絕對值不相等的非 00 整數,選出儘可能多的數,使得它們可以排成一個正負號交替,絕對值遞增的序列。給定 nn 和該序列,輸出最長的符合條件序列的長度。
  • 序列中元素不一定要按照輸入順序排列。1n5×1051 \leq n \leq 5 \times 10^5

[Soluntion]\color{blue}{\texttt{[Soluntion]}}

貪心。

直接將原數據按絕對值從小到大排序,然後把第一個數給選了,再枚舉,如果當前數的符號和上一個選的數的符號相反,就把它給選了。

下面是個人的證明,各位 dalao 不想看就不看了。

假設我們現在在考慮第 ii 個元素選或不選,有兩種情況:

  • ii 不能選。

    因爲我們已經將原序列按絕對值從小到大排序了,所以不存在說第 ii 個數因爲絕對值小於前一個選擇的數而不能選的情況。那麼就只剩下一種情況了:那就是 ii 和前一個被現在的數的符號相同。

    既然兩個數符號相同,那麼必然是有我不能有你,有你不能有我,可以用 ii 替代前一個數,但是沒必要,畢竟答案是不變的,沒必要給自己增加麻煩。

    綜上:當 ii 不能選時,不選。

  • ii 可以選。

    可能大家會有個這樣的擔心,會不會答案中 ii 是不選的,但是我們卻誤認爲 ii 是可以選的呢?

    答案是否定的。爲什麼呢?第一,因爲絕對值比 ii 小的數我們都已經考慮到了,現在我們就不考慮了。第二,如果 ii 不選,必然會有另一個數 jj 來代替 ii(否則 ii 就是最後一個數,直接選更優)。

    根據第一,j>i|j|>|i|,既然 iijj 也是有其一無其二,那麼我們選一個絕對值小的元素給後面的選擇可以留下更大的空間。

    綜上:當 ii 可以選時,必須選。

[code]\color{blue}{\texttt{[code]}}

#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
	char c=0;int x=0;bool f=0;
	while (!g(c)) f=c=='-',c=gc;
	while (g(c)) x=x*10+c-48,c=gc;
	return f?-x:x;
}
const int N=5e5+100;
int a[N],ans,n,test_number;
inline bool cmp(int x,int y){
	return abs(x)<abs(y);
}
inline bool check(int f,int l){
	if (a[f]/abs(a[f])==a[l]/abs(a[l]))
		return false;//符號不相反,不符合題意 
	else return true;//已經排序不用考慮絕對值 
}
int main(){
	test_number=read();//組數 
	while (test_number--){
		ans=1;n=read();//輸入加上初始化 
		for(int i=1;i<=n;i++) a[i]=read();
		sort(a+1,a+n+1,cmp);//按絕對值排序 
		for(register int i=2,lst=1;i<=n;i++)
			if (check(i,lst)){ans++;lst=i;}
		printf("%d\n",ans);//輸出答案 
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章