Submission #1192624

#TimeUsernameProblemLanguageResultExecution timeMemory
1192624hyakupRadio Towers (IOI22_towers)C++20
0 / 100
298 ms40160 KiB
#include "towers.h"
#include <bits/stdc++.h>
using namespace std;

using pii = pair<int, int>;

const int inf = 2e9;
const int maxn = 1e5 + 10;
const int logn = 20;

int n;
vector<int> h, vr, vl;

class Persistent_Segtree{
private:
  vector<int> l, r, sum;

  int create(){
    l.push_back(0);
    r.push_back(0);
    sum.push_back(0);

    return l.size() - 1;
  }

  int left( int pos ){
    if( l[pos] == 0 ){ int aux = create(); l[pos] = aux; }
    return l[pos];
  }

  int right( int pos ){
    if( r[pos] == 0 ){ int aux = create(); r[pos]  = aux; }
    return r[pos];
  }

public:

  int update( int pos, int ini, int fim, int id, int val ){
    int novo = create();
    if( ini > id || id > fim ) return novo;
    if( ini == fim ){ sum[novo] = 1; return novo; }

    int mid = ( ini + fim )/2;

    if( id <= mid ){ l[novo] = update( left(pos), ini, mid, id, val ); r[novo] = right(pos); }
    else{ l[novo] = left(pos); r[novo] = update( right(pos), mid + 1, fim, id, val ); }

    sum[novo] = sum[l[novo]] + sum[r[novo]];
    return novo;
  }

  int query( int pos, int ini, int fim, int ki, int kf ){
    if( ki > fim || ini > kf || pos == 0 ) return 0;
    if( ki <= ini && fim <= kf ) return sum[pos];

    int mid = ( ini + fim )/2;

    return query( left(pos), ini, mid, ki, kf ) + query( right(pos), mid + 1, fim, ki, kf );
  }

  Persistent_Segtree(){ create(); create(); }
} seg;


vector<pii> roots( 1, pii( inf, 1 ) );

void init(int N, vector<int> H) {
  h = H;
  n = N;
  vr.resize(n);
  vl.resize(n);
  // achar primeiro menor a esq e dir
  vector<int> l(n, -1), r(n, n);
  stack<pair<int, int>> pilha;
  pilha.push({-1, -inf});
  for( int i = 0; i < n; i++ ){
    while( pilha.top().second > h[i] ){
      r[pilha.top().first] = i;
      pilha.pop();
    }
    l[i] = pilha.top().first;
    pilha.push({ i, h[i] });
  }

  vector<vector<int>> maxi( n, vector<int>(logn));
  for( int i = 0; i < n; i++ ) maxi[i][0] = h[i];
  for( int k = 1; k < logn; k++ )
    for( int i = 0; i < n - (1<<k) + 1; i++ ) maxi[i][k] = max( maxi[i][k - 1], maxi[i + (1<<(k - 1))][k - 1] );

  auto query = [&]( int a, int b ){
    if( a > b ) return -inf;
    int k = 31 - __builtin_clz(b - a + 1);
    return max( maxi[a][k], maxi[b - (1<<k) + 1][k] );
  };

  vector<pii> v(n);

  for( int i = 0; i < n; i++ ){
    if( l[i] == -1 ) vl[i] = inf;
    else vl[i] = query(l[i] + 1, i - 1) - h[i];
    if( r[i] == n ) vr[i] = inf;
    else vr[i] = query(i + 1, r[i] - 1) - h[i];
    v[i].first = min( vl[i], vr[i] );
    v[i].second = i;
  }

  sort( v.rbegin(), v.rend() );


  for( auto [val, id] : v ){
    auto [last_val, last_root] = roots.back();
    int nova_root = seg.update( last_root, 0, n - 1, id, 1 );
    if( val == last_val ) roots.pop_back();
    roots.push_back({ val, nova_root });
  }

  reverse( roots.begin(), roots.end() );
}

int max_towers(int l, int r, int d) {
  int id = upper_bound( roots.begin(), roots.end(), pii( d, -inf ) ) - roots.begin();
  int root = roots[id].second;
  int resp = seg.query( root, 0, n - 1, l + 1, r - 1 );
  if( vr[l] >= d ) resp++;
  if( vl[r] >= d ) resp++;

  return resp;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...