dmkozyrev

563.cpp

Apr 2nd, 2018
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.95 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <assert.h>
  5. #include <stdint.h>
  6. #include <vector>
  7. #include <algorithm>
  8.  
  9. // Функция, возвращающая бит числа num в разряде pos
  10. inline int bit(int num, int pos) {
  11.     return num & (1LL << pos);
  12. }
  13.  
  14. // Рекурсивная поразрядная сортировка вектора:
  15. void bits_sort(std::vector<int>& v, int begin, int end, int level) {
  16.     if (begin == end || level == 32) return;
  17.     int len0, len1;
  18.     {
  19.         std::vector<int> equal0, equal1; // Две части массива: содержащие 0 и содержащие 1 в текущем разряде
  20.        
  21.         for (int i = begin; i <= end; ++i) {
  22.             if (bit(v[i], level) == 0) {
  23.                 equal0.push_back(v[i]);
  24.             } else {
  25.                 equal1.push_back(v[i]);
  26.             }
  27.         }
  28.        
  29.         len0 = (int)equal0.size();
  30.         len1 = (int)equal1.size();
  31.        
  32.         int i = begin;
  33.         for (int j = 0; j < len0; v[i++] = equal0[j++]);
  34.         for (int j = 0; j < len1; v[i++] = equal1[j++]);        
  35.     }
  36.     // Рекурсивные вызовы от обоих частей:
  37.     if (len0 > 1) bits_sort(v,      begin, begin+len0-1, level+1);
  38.     if (len1 > 1) bits_sort(v, begin+len0,          end, level+1);
  39. }
  40.  
  41. // Решение задачи:
  42. int solve(std::vector<int> arr) {
  43.     // Вычисляем XOR от всех чисел массива arr:
  44.     int s = 0; for (auto it : arr) s ^= it;
  45.    
  46.     // Применяем побитовую сортировку:
  47.     bits_sort(arr, 0, (int)arr.size()-1, 0);
  48.  
  49.     // Основной цикл по числам:
  50.     for (int i = 0; i < (int)arr.size()-1; ++i) {
  51.         int low = i+1, high = (int)arr.size()-1;
  52.         // Цикл по разрядам:
  53.         for (int pos = 0; high >= low && pos < 32; ++pos) {
  54.             // Разобьем оставшуюся часть массива на две группы:
  55.             // [low,  mid) - разряд на позиции pos совпадает с соответствующим разрядом числа a[i]
  56.             // [mid, high] - разряд на позиции pos не совпадает с соответствующим разрядом числа a[i]
  57.            
  58.             // Находим mid бинпоиском:
  59.             int mid;
  60.             if (bit(arr[i], pos) == bit(arr[low], pos)) {
  61.                 if (bit(arr[i], pos) != bit(arr[high], pos)) {
  62.                     int l = low, h = high;
  63.                     while (h - l > 1) {
  64.                         int m = (l + h) / 2;
  65.                         if (bit(arr[i], pos) == bit(arr[m], pos)) {
  66.                             l = m;
  67.                         } else {
  68.                             h = m;
  69.                         }
  70.                     }
  71.                     mid = h;
  72.                 } else {
  73.                     mid = high + 1;
  74.                 }
  75.             } else {
  76.                 mid = low;
  77.             }
  78.             // Результат:
  79.             // бит совпадает для всех чисел от [low, mid)
  80.             // high-mid+1 чисел имеют общий префикс длиной pos
  81.             if ((high-mid+1) % 2 == 1) { // Обновляем результат:
  82.                 s ^= (1 << pos) - 1;
  83.             }
  84.             high = mid-1; // спуск к тем числам, разряд у которых совпал
  85.         }
  86.         if (high >= low && (high-low+1) % 2 == 1) { // Обрабатываем последнюю группу - группу чисел с максимальным префиксом = 32:
  87.             s ^= -1;
  88.         }
  89.     }
  90.     return s;
  91. }
  92.  
  93. int main() {
  94.     freopen("input.txt", "rt", stdin);
  95.     int n; scanf("%d", &n);
  96.     std::vector<int> a(n); for (auto & it : a) scanf("%d", &it);
  97.     printf("%d", solve(a));
  98.    
  99.     return 0;
  100. }
Advertisement
Add Comment
Please, Sign In to add comment