func_code_string: #include <bits/stdc++.h>   using namespace std;   const int INF = 1e9 + 5;   struct segment_change {     int to_add;     segment_change(int _to_add = 0) : to_add(_to_add) {}     void reset() { to_add = 0; }     bool has_change() const { return to_add != 0; }     segment_change combine(const segment_change &other) const {       return segment_change(to_add + other.to_add);     }   };   struct segment {     int maximum;     segment(int _maximum = -INF) : maximum(_maximum) {}     void apply(int, const segment_change &change) { maximum += change.to_add; }     void join(const segment &other) { maximum = max(maximum, other.maximum); }     void join(const segment &a, const segment &b) {       *this = a;       join(b);     }   };   struct add_max_seg_tree {     int tree_n = 0;     vector<segment> tree;     vector<segment_change> changes;     add_max_seg_tree(int n = 0) {       if (n > 0) init(n);     }     void init(int n) {       tree_n = 1;       while (tree_n < n) tree_n *= 2;       tree.assign(2 * tree_n, segment());       changes.assign(tree_n, segment_change());     }     void build(const vector<segment> &initial) {       int n = initial.size();       assert(n <= tree_n);       for (int i = 0; i < n; i++) tree[tree_n + i] = initial[i];       for (int position = tree_n - 1; position > 0; position--)         tree[position].join(tree[2 * position], tree[2 * position + 1]);     }     void push_down(int position, int length) {       if (!changes[position].has_change()) return;       if (2 * position < tree_n) {         changes[2 * position] = changes[2 * position].combine(changes[position]);         changes[2 * position + 1] =             changes[2 * position + 1].combine(changes[position]);       }       tree[2 * position].apply(length / 2, changes[position]);       tree[2 * position + 1].apply(length / 2, changes[position]);       changes[position].reset();     }     void push_all(int a, int b) {       assert(0 <= a && a < b && b <= tree_n);       a += tree_n;       b += tree_n - 1;       for (int up = 31 - __builtin_clz(tree_n); up > 0; up--) {         int x = a >> up, y = b >> up;         push_down(x, 1 << up);         if (x != y) push_down(y, 1 << up);       }     }     void join_and_apply(int position, int length) {       tree[position].join(tree[2 * position], tree[2 * position + 1]);       tree[position].apply(length, changes[position]);     }     void join_all(int a, int b) {       assert(0 <= a && a < b && b <= tree_n);       a += tree_n;       b += tree_n - 1;       int length = 1;       while (a > 1) {         a /= 2;         b /= 2;         length *= 2;         join_and_apply(a, length);         if (a != b) join_and_apply(b, length);       }     }     pair<int, int> right_half[32];     template <typename T_range_op>     void process_range(int a, int b, bool needs_join, T_range_op &&range_op) {       if (a == b) return;       push_all(a, b);       int original_a = a, original_b = b;       int length = 1, r_size = 0;       for (a += tree_n, b += tree_n; a < b; a /= 2, b /= 2, length *= 2) {         if (a & 1) range_op(a++, length);         if (b & 1) right_half[r_size++] = {--b, length};       }       for (int i = r_size - 1; i >= 0; i--)         range_op(right_half[i].first, right_half[i].second);       if (needs_join) join_all(original_a, original_b);     }     segment query(int a, int b) {       assert(0 <= a && a <= b && b <= tree_n);       segment answer;       process_range(a, b, false,                     [&](int position, int) { answer.join(tree[position]); });       return answer;     }     void update(int a, int b, const segment_change &change) {       assert(0 <= a && a <= b && b <= tree_n);       process_range(a, b, true, [&](int position, int length) {         tree[position].apply(length, change);         if (position < tree_n)           changes[position] = changes[position].combine(change);       });     }     void set_value(int index, int value) {       assert(0 <= index && index < tree_n);       int current = query(index, index + 1).maximum;       update(index, index + 1, segment_change(value - current));     }   };   int N;   vector<int> parent;   vector<vector<int>> children;   vector<int> tour_start, tour_end;   int tour;   void dfs(int node) {     tour_start[node] = tour++;     for (int child : children[node]) dfs(child);     tour_end[node] = tour;   }   template <typename T>   ostream &operator<<(ostream &os, const vector<T> &v) {     os <<  { ;     for (typename vector<T>::const_iterator vi = v.begin(); vi != v.end(); ++vi) {       if (vi != v.begin()) os <<  ,  ;       os << *vi;     }     os <<  } ;     return os;   }   template <>   ostream &operator<<(ostream &os, const vector<string> &v) {     os <<  { ;     for (vector<string>::const_iterator vi = v.begin(); vi != v.end(); ++vi) {       if (vi != v.begin()) os <<  ,  ;       os <<     << *vi <<    ;     }     os <<  } ;     return os;   }   vector<int> solve(vector<int> perm) {     assert((int)perm.size() == N);     assert(perm.front() == 1);     for (int &p : perm) p--;     parent.assign(N, -1);     vector<pair<int, int>> events;     vector<int> stack = {-1};     for (int x : perm) {       int erased = -1;       while (stack.back() > x) {         erased = stack.back();         stack.pop_back();       }       events.emplace_back(x, stack.back());       events.emplace_back(erased, x);       parent[x] = stack.back();       if (erased >= 0) parent[erased] = x;       stack.push_back(x);     }     children.assign(N, {});     tour_start.resize(N);     tour_end.resize(N);     for (int i = 0; i < N; i++)       if (parent[i] >= 0) children[parent[i]].push_back(i);     tour = 0;     dfs(0);     vector<int> answers(N, INF);     add_max_seg_tree tree(N);     for (int i = 0; i < N; i++) {       int a = events[2 * i].first;       int b = events[2 * i].second;       assert(a >= 0);       tree.set_value(           tour_start[a],           b < 0 ? 1 : tree.query(tour_start[b], tour_start[b] + 1).maximum + 1);       a = events[2 * i + 1].first;       b = events[2 * i + 1].second;       if (a >= 0) {         tree.update(tour_start[a], tour_end[a], segment_change(+1));       }       answers[i] = tree.query(0, N).maximum;     }     return answers;   }   vector<int> A;   int main() {     ios::sync_with_stdio(false);     cin.tie(nullptr);     cin >> N;     A.resize(N);     for (int &a : A) cin >> a;     int one = find(A.begin(), A.end(), 1) - A.begin();     vector<int> start_one, end_one;     for (int i = one; (int)start_one.size() < N; i = (i + 1) % N)       start_one.push_back(A[i]);     for (int i = one; (int)end_one.size() < N; i = (i + N - 1) % N)       end_one.push_back(A[i]);     vector<int> left = solve(end_one), right = solve(start_one);     int best_left = 0, best = INF;     for (int i = 0; i < N; i++) {       if (max(left[i], right[N - 1 - i]) < best) {         best = max(left[i], right[N - 1 - i]);         best_left = i;       }     }     cout << best <<     << (one - best_left + N) % N <<   n ;   }   