#pragma once #include #include #include template bool compare_default (const T &l, const T &r) { return l == r; } template bool find_vec (std::vector &vec, const T &value, const std::function &callback, std::function compare = compare_default , bool sorted = false) { const size_t n = vec.size (); if (!compare) compare = compare_default; if (sorted) { size_t left = 0, right = n; while (left < right) { size_t mid = left + (right - left) / 2; if (compare (vec [mid], value)) { callback (mid); return true; } if (vec [mid] < value) left = mid + 1; else right = mid; } return false; } if (n < 64) { for (size_t i = 0; i < n; i++) { if (compare (vec [i], value)) { callback (i); return true; } } return false; } const size_t blockSize = 8; size_t i = 0; for (; i + blockSize <= n; i += blockSize) { for (size_t j = 0; j < blockSize; j ++) { if (compare (vec [i + j], value)) { callback (i + j); return true; } } } for (; i < n; i ++) { if (compare (vec [i], value)) { callback (i); return true; } } return false; } template void push_unique (std::vector &vec, const T &value, std::function compare = compare_default ) { bool found = find_vec ( vec, value, [] (size_t) {}, compare); if (!found) vec.push_back (value); } template void push_normal (std::vector &vec, const T &value) { vec.push_back (value); } template void push_normal (std::vector &target, const std::vector &another) { target.insert (target.end (), another.begin (), another.end ()); }