Submission #1293344

#TimeUsernameProblemLanguageResultExecution timeMemory
1293344julia_08Dancing Elephants (IOI11_elephants)C++20
100 / 100
6305 ms13812 KiB
#pragma GCC optimize ("unroll-loops")
#pragma GCC optimize ("Ofast")

#include <bits/stdc++.h>
#include "elephants.h"

using namespace std;

const int MAXN = 2e5 + 10;
const int INF = 1e9;

const int B = 1500; // :(
const int UPD = 387;

int x[MAXN], ind[MAXN];

pair<int, int> suf[MAXN];

set<pair<int, int>> s;

vector<vector<pair<int, int>>> buckets;

int n, l;

int cnt_upd = 0;

void process(int id){

  auto &b = buckets[id];

  if(b.empty()) return;

  int sz = (int) b.size();

  int r = sz - 1;

  for(int i=(sz - 1); i>=0; i--){

    while(b[r].first - b[i].first > l) r--;

    int last = 0;

    if(r < sz - 1) last = suf[b[r + 1].second].first;

    int extra = (b[i].first + l) - b[sz - 1].first;

    if(r < sz - 1) extra = suf[b[r + 1].second].second;

    suf[b[i].second] = {last + 1, extra};

  }

}

void create_buckets(){

  int cnt = 0;

  buckets.clear();
  buckets.push_back({});

  for(auto x : s){

    if(cnt < B){

      buckets.back().push_back(x);
      cnt ++;

    } else{

      buckets.push_back({x});
      cnt = 1;

    }

    ind[x.second] = (int) buckets.size() - 1;

  }

  for(int i=0; i<(int) buckets.size(); i++) process(i);

}

void refresh(){

  cnt_upd ++;

  if(cnt_upd == UPD){
    create_buckets();
    cnt_upd = 0;
  }

}

int find_bucket(int x){

  for(int i=0; i<(int) buckets.size(); i++){
    if(!buckets[i].empty() && x <= buckets[i].back().first){
      return i;
    }
  }

  return (int) buckets.size() - 1;

}

void remove(int id){

  int j = ind[id];

  for(int i=0; i<buckets[j].size(); i++){
    if(buckets[j][i].second == id){
      buckets[j].erase(buckets[j].begin() + i);
      break;
    }
  }  

  s.erase({x[id], id});
  process(j);

}

void add(int id){

  int j = find_bucket(x[id]);
  ind[id] = j;

  for(int i=0; i<buckets[j].size(); i++){

    if(x[id] < buckets[j][i].first){
      buckets[j].insert(buckets[j].begin() + i, {x[id], id});
      break;
    }

  }
  
  if(buckets[j].empty() || x[id] >= buckets[j].back().first){
    buckets[j].push_back({x[id], id});
  }

  s.insert({x[id], id});
  process(j);

}

int query(){

  int ans = 0;

  int cur = s.begin()->second;

  while(true){

    ans += suf[cur].first;

    int nxt = buckets[ind[cur]].back().first + suf[cur].second;
    auto pos = s.upper_bound({nxt, INF});

    if(pos == s.end()) break;
    cur = pos->second;

  }

  return ans;

}

void init(int n_, int l_, int x_[]){

  n = n_;
  l = l_;

  cnt_upd = 0;

  for(int i=0; i<n; i++) x[i] = x_[i];

  s.clear();

  for(int i=0; i<n; i++) s.insert({x[i], i});

  create_buckets();

}

int update(int id, int y){

  remove(id);

  x[id] = y;

  add(id);

  refresh();

  return query();

}
#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...