- 有 個絕對值不相等的非 整數,選出儘可能多的數,使得它們可以排成一個正負號交替,絕對值遞增的序列。給定 和該序列,輸出最長的符合條件序列的長度。
- 序列中元素不一定要按照輸入順序排列。。
貪心。
直接將原數據按絕對值從小到大排序,然後把第一個數給選了,再枚舉,如果當前數的符號和上一個選的數的符號相反,就把它給選了。
下面是個人的證明,各位 dalao
不想看就不看了。
假設我們現在在考慮第 個元素選或不選,有兩種情況:
-
不能選。
因爲我們已經將原序列按絕對值從小到大排序了,所以不存在說第 個數因爲絕對值小於前一個選擇的數而不能選的情況。那麼就只剩下一種情況了:那就是 和前一個被現在的數的符號相同。
既然兩個數符號相同,那麼必然是有我不能有你,有你不能有我,可以用 替代前一個數,但是沒必要,畢竟答案是不變的,沒必要給自己增加麻煩。
綜上:當 不能選時,不選。
-
可以選。
可能大家會有個這樣的擔心,會不會答案中 是不選的,但是我們卻誤認爲 是可以選的呢?
答案是否定的。爲什麼呢?第一,因爲絕對值比 小的數我們都已經考慮到了,現在我們就不考慮了。第二,如果 不選,必然會有另一個數 來代替 (否則 就是最後一個數,直接選更優)。
根據第一,,既然 和 也是有其一無其二,那麼我們選一個絕對值小的元素給後面的選擇可以留下更大的空間。
綜上:當 可以選時,必須選。
#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);//輸出答案
}
}