BOJ 16209 - 수열 섞기

image.png

덱을 이용한 그리디로 풀 수 있다.

인접한 수들의 합의 최대값은 덱에 가장 큰 수부터 넣고, 그 다음 큰수들부터 앞 뒤 앞 뒤로 붙여나가면 된다.

다만, $a_i < 0$ 인 것도 있으므로 음수 양수를 따로 분리해서 위와 같이 두 합칠 배열을 만들어준다.

음수 쪽에선 $a_i$가 가장 큰 것을 뒤로 가게 해주고, 양수 쪽에선 $a_i$ 가 가장 작은것을 앞으로 가게 해준다.

음수 + $0,0,\dots,0$ + 양수

배열처럼 합쳐주면 정답이다.

void solve() {  
   int n;  
   cin >> n;  
   vi a(n);  
   fv(a);  
   sort(all(a));  
   int zero = ubi(a, 0) - lbi(a, 0);  
   int minus = lbi(a, 0);  
   int plus = n - zero - minus;  
  
   vi negative(a.begin(), a.begin() + minus);  
   vi positive(a.begin() + zero + minus, a.end());  
  
   auto generate = [&](vi a) -> deque<int> {  
      for (int &i: a) i = abs(i);  
      sort(all(a), greater<>());  
      deque<int> b;  
      for (int i = 0; i < sz(a); i++) {  
         if (i & 1) b.push_back(a[i]);  
         else b.push_front(a[i]);  
      }  
      return b;  
   };  
  
   auto pos_dq = generate(positive);  
   auto neg_dq = generate(negative);  
   for (int &i: neg_dq) i *= -1;  
  
   if (sz(pos_dq) && pos_dq.front() > pos_dq.back()) reverse(all(pos_dq));  
   if (sz(neg_dq) && neg_dq.back() < neg_dq.front()) reverse(all(neg_dq));  
  
   for (int i: neg_dq) cout << i << ' ';  
   for (int i = 0; i < zero; i++) cout << 0 << ' ';  
   for (int i: pos_dq) cout << i << ' ';  
}

Tags:

Categories:

Updated:

Comments