template T min(T a, T b) {     return (a > b) ? b : a; }   template T max(T a, T b) {     return (a < b) ? b : a; }   template struct Vqs {       Vqs();       unsigned int count();     bool empty();     bool full();     void clear();     void print();       T& get_front();     T& get_back();     T& pop_back();     void push_back(T v);     T& pop_front();       void set(int index, T value);     T& get(int index);     int insert(int i, T in[], int count);     int sai(int i, int count, T indata[]);     int del(int i, int count);       int front;     int back;     T data[N]; };   template void Vqs::clear() {     front = 0;     back = 0; }   template Vqs::Vqs() {     clear(); }   template bool Vqs::empty() {     return front == back; }   template bool Vqs::full() {     return back - front == N; }   template unsigned int Vqs::count() {     return back - front; }   template void Vqs::print() {       int i = 0;     int end = back - front;     std::cout << "\n";       while (i < end) {         std::cout << data[(front + i++) % N] << ", ";     } }   template T& Vqs::get_front() {     return data[front % N]; }   template T& Vqs::get_back() {     return data[(back - 1) % N]; }   template T& Vqs::get(int index) {     return data[index]; }   template void Vqs::set(int i, T value) {     data[(front + i) % N] = value; }   template void Vqs::push_back(T v) {       if (front + N == back) {         ++front;     }       data[back++ % N] = v; }   template T& Vqs::pop_back() {       assert(front != back);     return data[--back % N]; }   template T& Vqs::pop_front() {       assert(front != back);     return data[front++ % N]; }   template int Vqs::sai(int i, int count, T indata[]) {       int after_i = back - front - i;       if (after_i < 0) {         return 0;     }       //init     int b_count, b_after_i, startj, to_delete;       if (count < 0) {         startj = i - 1;         to_delete = ::min(after_i, -count);     }     else     {         startj = ::max(N - count, after_i) - 1;         b_count = back + count;         b_after_i = back - after_i;     }       //process     int src, dst;       for (int j = startj; j >= 0; --j) {         if (count < 0) {             dst = front + to_delete + j;             src = dst - to_delete;         }         else {             dst = b_after_i + count + j;             src = dst - count;         }         data[dst % N] = data[src % N];     }       // postprocess     if (count < 0) {         front += to_delete;         return to_delete;     }     else {           int front_candidate = b_count - N;           if (front_candidate > front) {             front = ::min(front_candidate, b_after_i);         }           back = ::min(b_count, b_after_i + N);           for (int j = 0; j < count; ++j) {             data[(front + i + j) % N] = indata[j];         }           return count;     } }   template int Vqs::del(int i, int count) {     return sai(i, -count, nullptr); }   template int Vqs::insert(int i, T in[], int count) {     return sai(i, count, in); }