제출 #1336913

#제출 시각아이디문제언어결과실행 시간메모리
1336913SmuggingSpunEqualmex (CEOI25_equalmex)C++20
100 / 100
1706 ms100924 KiB
#include<bits/stdc++.h>
using namespace std;
template<class T>void minimize(T& a, T b){
  if(a > b){
    a = b;
  }
}
int n, q;
vector<int>a;
vector<pair<int, int>>query;
namespace sub123{
  const int lim = 1e3 + 5;
  bitset<lim>cnt;
  vector<int>solve(){
    vector<int>ret;
    for(auto& [l, r] : query){
      cnt.reset();
      int mex_lr = 1;
      for(int i = l; i <= r; i++){
        cnt[a[i]] = true;
        while(cnt[mex_lr]){
          mex_lr++;
        }
      }
      if(mex_lr == 1){
        ret.push_back(r - l + 1);
        continue;
      }
      int ans = 0;
      for(int i = l; i <= r; ){
        cnt.reset();
        int mex = 1;
        while(i <= r && mex < mex_lr){
          cnt[a[i++]] = true;
          while(cnt[mex]){
            mex++;
          }
        }
        if(mex < mex_lr){
          break;
        }
        ans++;
      }
      ret.push_back(ans);
    }
    return ret;
  }
}
namespace sub4{
  vector<int>solve(){
    for(int& x : a){
      x--;
    }
    vector<vector<int>>nxt(n + 1, vector<int>(2, n)), up(20, vector<int>(n + 2, n + 1));
    for(int i = n - 2; i > -1; i--){
      nxt[i] = nxt[i + 1];
      nxt[i][a[i + 1]] = i + 1;
    }
    for(int i = 0; i < n; i++){
      up[0][i] = nxt[i][a[i] ^ 1] + 1;
    }
    for(int i = 1; i < 20; i++){
      for(int j = 0; j < n; j++){
        up[i][j] = up[i - 1][up[i - 1][j]];
      }
    }
    vector<int>ret;
    for(auto& [l, r] : query){
      int ans = 0;
      for(int bit = 19; bit > -1; bit--){
        if(up[bit][l] < r + 2){
          l = up[bit][l];
          ans |= 1 << bit;
        }
      }
      ret.push_back(ans == 0 ? r - l + 1 : ans);
    }
    return ret;
  }
}
namespace sub56{
  const int lim = 6e5 + 5;
  const int LIM = 4e5 + 5;
  int st[LIM << 2], in_pos[LIM];
  vector<int>mex_1, mex_2, ans, event[lim];
  void update(int id, int l, int r, int p, int x){
    if(l == r){
      st[id] = x;
      return;
    }
    int m = (l + r) >> 1;
    if(m < p){
      update(id << 1 | 1, m + 1, r, p, x);
    }
    else{
      update(id << 1, l, m, p, x);
    }
    st[id] = min(st[id << 1], st[id << 1 | 1]);
  }
  int walk(int x){
    int id = 1, l = 1, r = LIM;
    while(l < r){
      int m = (l + r) >> 1;
      if(st[id <<= 1] >= x){
        id |= 1;
        l = m + 1;
      }
      else{
        r = m;
      }
    }
    return l;
  }
  vector<int>work(){
    memset(st, -1, sizeof(st));
    for(int i = 0; i < n; i++){
      event[i].clear();
    }
    for(int i = 0; i < q; i++){
      if(query[i].first <= query[i].second){
        event[query[i].second].push_back(i);
      }
    }
    vector<int>mex(q, 0);
    for(int r = 0; r < n; r++){
      update(1, 1, LIM, a[r], r);
      for(int& i : event[r]){
        mex[i] = walk(query[i].first);
      }
    }
    return mex;
  }
  struct Data{
    int mex, cnt, last;
    Data(){}
    Data(int _mex, int _cnt, int _last) : mex(_mex), cnt(_cnt), last(_last) {}
  };
  Data left[lim], right[lim];
  void dnc(int l, int r){
    if(l > r){
      return;
    }
    int m = (l + r) >> 1;
    left[m] = Data(0, 0, m);
    set<int>s;
    for(int i = m - 1, mex = 1; i >= l; i--){
      if(in_pos[a[i]] != -1 && a[i] < mex){
        s.erase(in_pos[a[i]]);
      }
      if(a[in_pos[a[i]] = i] < mex){
        s.insert(i);
      }
      while(in_pos[mex] != -1){
        s.insert(in_pos[mex++]);
      }
      if(mex == 1){
        left[i] = Data(1, m - i, m);
      }
      else if(mex != left[i + 1].mex){
        left[i] = Data(mex, 1, *s.rbegin() + 1);
      }
      else{
        int other = *s.rbegin() + 1;
        if(left[other].mex == mex){
          left[i] = left[other];
          left[i].cnt++;
        }
        else{
          left[i] = Data(mex, 1, other);
        }
      }
    }
    s.clear();
    for(int i = m - 1; i >= l; i--){
      in_pos[a[i]] = -1;
    }
    if(m > 0){
      right[m - 1] = Data(0, 0, m - 1);
    }
    for(int i = m, mex = 1; i <= r; i++){
      if(in_pos[a[i]] != -1 && a[i] < mex){
        s.erase(in_pos[a[i]]);
      }
      if(a[in_pos[a[i]] = i] < mex){
        s.insert(i);
      }
      while(in_pos[mex] != -1){
        s.insert(in_pos[mex++]);
      }
      if(mex == 1){
        right[i] = Data(1, i - m + 1, m - 1);
      }
      else if(i == m || mex != right[i - 1].mex){
        right[i] = Data(mex, 1, *s.begin() - 1);
      }
      else{
        int other = *s.begin() - 1;
        if(other != -1 && right[other].mex == mex){
          right[i] = right[other];
          right[i].cnt++;
        }
        else{
          right[i] = Data(mex, 1, other);
        }
      }
      while(!event[i].empty()){
        int qid = event[i].back();
        auto& [lq, rq] = query[qid];
        if(lq > m){
          break;
        }
        event[i].pop_back();
        if(right[rq].mex == mex_1[qid]){
          ans[qid] += right[rq].cnt;
          rq = right[rq].last;
        }
        if(left[lq].mex == mex_1[qid]){
          ans[qid] += left[lq].cnt;
          lq = left[lq].last;
        }
      }
    }
    for(int i = m; i <= r; i++){
      in_pos[a[i]] = -1;
    }
    dnc(l, m - 1);
    dnc(m + 1, r);
  }
  vector<int>solve(){
    mex_1 = work();
    for(int i = 0; i < n; i++){
      sort(event[i].begin(), event[i].end(), [&] (int x, int y){
        return query[x].first > query[y].first;
      });
    }
    memset(in_pos, -1, sizeof(in_pos));
    ans.assign(q, 0);
    dnc(0, n - 1);
    mex_2 = work();
    for(int i = 0; i < q; i++){
      if(mex_1[i] == mex_2[i]){
        ans[i]++;
      }
    }
    return ans;
  }
}
vector<int>solve(int __n, vector<int>& __v, int __q, vector<pair<int, int>>& __query){
  a = __v;
  n = __n;
  query = __query;
  for(int& i : a){
    minimize(i, n + 2);
  }
  if(max(n, q = __q) <= 1000){
    return sub123::solve();
  } 
  if(*max_element(a.begin(), a.end()) < 3){
    return sub4::solve();
  }
  return sub56::solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...