Advertisement
erek1e

IOI '04 P6 - Empodia

Jun 25th, 2023
858
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.00 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <stack>
  4. #include <climits>
  5.  
  6. using namespace std;
  7.  
  8. int main() {
  9.     int n; cin >> n;
  10.     vector<int> a(n);
  11.     for (int &x : a) cin >> x;
  12.  
  13.     // For each index i, find smallest j s.t. j > i and a[j] < a[i]
  14.     vector<int> nextSmaller(n, n);
  15.     stack<int> st;
  16.     for (int i = n-1; i >= 0; --i) {
  17.         while (!st.empty() && a[st.top()] >= a[i]) st.pop();
  18.         if (!st.empty()) nextSmaller[i] = st.top();
  19.         st.push(i);
  20.     }
  21.  
  22.     // Find smallest framed interval starting at each index
  23.     vector<pair<int, int>> candidates; // framed intervals
  24.  
  25.     stack<int> maximums; // maximums since start
  26.     // Let dif[i] = a[i] - i
  27.     vector<vector<int>> maxByDif(2*n-1); // -(n-1) to n-1
  28.     auto dif = [&](int i) { // adding n-1 to avoid negatives
  29.         return a[i] - i + n-1;
  30.     };
  31.  
  32.     for (int s = n-1; s >= 0; --s) { // fix start
  33.         // remove old maximums
  34.         while (!maximums.empty() && a[maximums.top()] <= a[s]) {
  35.             maxByDif[dif(maximums.top())].pop_back();
  36.             maximums.pop();
  37.         }
  38.  
  39.         if (!maxByDif[dif(s)].empty()) {
  40.             // first max since i with dif[j] = dif[i]
  41.             int r = maxByDif[dif(s)].back();
  42.             if (r < nextSmaller[s]) candidates.emplace_back(s, r);
  43.         }
  44.        
  45.         // add new maximum
  46.         maximums.push(s);
  47.         maxByDif[dif(s)].push_back(s);
  48.     }
  49.  
  50.     // Remove all framed intervals that contain others
  51.     //  intervals are ordered by left in decreasing order, and have distinct lefts
  52.     stack<pair<int, int>> empodia;
  53.     int closestFinish = INT_MAX;
  54.     for (auto [l, r] : candidates) {
  55.         if (closestFinish > r) {
  56.             empodia.emplace(l, r);
  57.             closestFinish = r;
  58.         }
  59.     }
  60.    
  61.     // Print empodia
  62.     cout << empodia.size() << endl;
  63.     while (!empodia.empty()) {
  64.         cout << 1+empodia.top().first << ' ' << 1+empodia.top().second << '\n';
  65.         empodia.pop();
  66.     }
  67.     return 0;
  68. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement