제출 #627357

#제출 시각아이디문제언어결과실행 시간메모리
627357ainta송신탑 (IOI22_towers)C++17
100 / 100
1837 ms52756 KiB
#include "towers.h"
#include <bits/stdc++.h>
using namespace std;
 
using ll=long long;
 
 
#define rng(i,a,b) for(int i=int(a);i<=int(b);i++)
#define rep(i,b) rng(i,0,b-1)
#define gnr(i,b,a) for(int i=int(b);i>=int(a);i--)
#define per(i,b) gnr(i,b-1,0)
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;
using pii=pair<int,int>;
using vi=vc<int>;
using uint=unsigned;
using ull=unsigned ll;
using pil=pair<int,ll>;
using pli=pair<ll,int>;
using pll=pair<ll,ll>;
using t3=tuple<int,int,int>;
#define N_ 101000
#define SZ 131072

int chk, w[N_], n, INF = 1e9 + 123;
//vi V;

struct Tree{
  pii IT[SZ+SZ];
  void Put(int a, int b){
    IT[a+SZ]={b,a};
    a+=SZ;
    while(a!=1){
      a>>=1;
      IT[a]=max(IT[a*2],IT[a*2+1]);
    }
  }
  pii Get(int b, int e){
    pii r={-INF,0};
    b+=SZ,e+=SZ;
    while(b<=e){
      r=max({r,IT[b],IT[e]});
      b=(b+1)>>1,e=(e-1)>>1;
    }
    return r;
  }
}T1,T2,U1,U2;

pii Max(int b, int e){
  return T1.Get(b,e);
}
pii Min(int b, int e){
  auto z = T2.Get(b,e);
  return {-z.fi, z.se};
}

struct Node{
  pii Mn, Mx;
  t3 ud, du;
}IT[SZ+SZ];
Node Merge (Node a, Node b){
  Node r;
  r.Mn = min(a.Mn,b.Mn);
  r.Mx = max(a.Mx,b.Mx);
  r.ud = max({a.ud, b.ud, {a.Mx.fi - b.Mn.fi, a.Mx.se, b.Mn.se} });
  r.du = max({a.du, b.du, {b.Mx.fi - a.Mn.fi, a.Mn.se, b.Mx.se} });
  return r;
}

void Put(int a){
  Node t = {{w[a],a}, {w[a],a}, {0,a,a}, {0,a,a}};
  a+=SZ;
  IT[a] = t;
  while(a!=1){
    a>>=1;
    IT[a] = Merge(IT[a*2],IT[a*2+1]);
  }
}
Node GetRange(int b, int e){
  b+=SZ,e+=SZ;
  vi TL, TR;
  while(b<=e){
    if(b&1)TL.pb(b);
    if(!(e&1))TR.pb(e);
    b=(b+1)>>1,e=(e-1)>>1;
  }
  reverse(all(TR));
  for(auto &t : TR)TL.pb(t);
  Node res = IT[TL[0]];
  rng(i,1,si(TL)-1){
    res = Merge(res, IT[TL[i]]);
  }
  return res;
}

int U[N_];
int isUp[N_];

priority_queue<t3>PQ;
set<int>Set;
void SetPut(int x, int d){
  auto it = Set.find(x);
  auto it2 = it;
  auto it3 = it;
  it2--;
  it3++;

  if(*it2 == 0){
    if(x>1){
      if(isUp[x]){
        auto [gg,u] = Min(1,x-1);
        if(w[x] > w[u]){
          PQ.push({w[x]-w[u], 0, u});
        }
      }
      else{
        auto [gg,u] = Max(1,x-1);
        if(w[x] < w[u]){
          PQ.push({w[u]-w[x], 0, u});
          isUp[u] = 1;
        }
      }
    }
  }
  else{
    int b = (*it2) + 1, e = (*it)-1;

    if(b<=e){
      if(isUp[x]){
        auto [p1,p2,p3,p4] = GetRange(b,e);
        if(get<0>(p3)>0){
          PQ.push(p3);
          isUp[get<1>(p3)] = 1;
        }
      }
      else{
        auto [p1,p2,p3,p4] = GetRange(b,e);
        if(get<0>(p4)>0){
          PQ.push(p4);
          isUp[get<2>(p4)] = 1;
        }
      }
    }
  }
  if(*it3 == n+1){
    if(x<n){
      if(isUp[x]){
        auto [gg,u] = Min(x+1,n);
        if(w[x] > w[u]){
          PQ.push({w[x]-w[u], 0, u});
        }
      }
      else{
        auto [gg,u] = Max(x+1,n);
        if(w[x] < w[u]){
          PQ.push({w[u]-w[x], 0, u});
          isUp[u] = 1;
        }
      }
    }

  }
  else{
    int b = (*it) + 1, e = (*it3)-1;

    if(b<=e){
      if(!isUp[x]){
        auto [p1,p2,p3,p4] = GetRange(b,e);
        if(get<0>(p3)>0){
          PQ.push(p3);
          isUp[get<1>(p3)] = 1;
        }
      }
      else{
        auto [p1,p2,p3,p4] = GetRange(b,e);
        if(get<0>(p4)>0){
          PQ.push(p4);
          isUp[get<2>(p4)] = 1;
        }
      }
    }
  }
}

int Root[N_];
struct PNode{
  int l, r, s;
};
PNode PST[N_*30];
int cnt;

void Add(int nd, int p, int l, int r, int x){
  PST[nd] = PST[p];
  int m = (l+r)>>1;
  PST[nd].s++;
  if(l==r)return;
  if(x<=m){
    PST[nd].l = ++cnt;
    Add(PST[nd].l, PST[p].l, l, m, x);
  }
  else{
    PST[nd].r = ++cnt;
    Add(PST[nd].r, PST[p].r, m+1, r, x);
  }
}

int Sum(int nd, int b, int e, int s, int l){
  if(s<=b&&e<=l)return PST[nd].s;
  if(s>l)return 0;
  int m = (b+e)>>1;
  int rr = 0;
  if(s<=m)rr += Sum(PST[nd].l, b, m, s, l);
  if(l>m) rr += Sum(PST[nd].r, m+1, e, s, l);
  return rr;
}


int Left(int nd, int b, int e, int s, int l){
  if(!PST[nd].s)return -1;
  if(b==e)return b;
  int m = (b+e)>>1;
  int rr = 0;
  if(s<=m){
    rr = Left(PST[nd].l, b, m, s, l);
    if(rr!=-1)return rr;
  }
  return Left(PST[nd].r, m+1, e, s, l);
}
int Right(int nd, int b, int e, int s, int l){
  if(!PST[nd].s)return -1;
  if(b==e)return b;
  int m = (b+e)>>1;
  int rr = 0;
  if(l>m){
    rr = Right(PST[nd].r, m+1, e, s, l);
    if(rr!=-1)return rr;
  }
  return Right(PST[nd].l, b, m, s, l);
}

vc<pii>V;

void init(int N, std::vector<int> H) {
  n = N;
  rng(i,1,N){
    w[i] = H[i-1];
    T1.Put(i,w[i]);
    T2.Put(i,-w[i]);
  }
  rng(i,1,n){
    Put(i);
  }
  auto [p1, p2, p3, p4] = GetRange(1,n);
  Set.insert(0);
  Set.insert(n+1);
  {
    if(get<0>(p3) < get<0>(p4)){
      PQ.push(p4);
      isUp[get<2>(p4)] = 1;
    }
    else{
      PQ.push(p3);
      isUp[get<1>(p3)] = 1;
    }
  }
  while(!PQ.empty()){
    
    auto [d,l,r] = PQ.top();
    //printf("! %d %d %d\n",d,l,r);
    PQ.pop();
    if(l!=0){
      Set.insert(l);
      if(!U[l])U[l] = d;
    }
    Set.insert(r);
    if(!U[r])U[r] = d;
    if(l)SetPut(l,d);
    SetPut(r,d);
  }
  rng(i,1,n){
    V.pb({U[i],i});
    U1.Put(i, U[i]);
  }
  sort(all(V));
  per(i,n){
    Root[i] = ++cnt;
    Add(Root[i], Root[i+1], 1, n, V[i].se);
  }
}


int max_towers(int L, int R, int D) {
  L++,R++;
  int pv = lower_bound(all(V), pii(D,-999)) - V.begin();
  int c = Sum(Root[pv], 1, n, L, R);
  if(!c)return 1;

  int bb = Left(Root[pv], 1, n, L, R);
  int ee = Right(Root[pv], 1, n, L, R);

  if(isUp[bb]){
    if(w[bb] - Min(L,bb-1).fi>= D) c++;
    else c--;
  }
  if(isUp[ee]){
    if(w[ee] - Min(ee+1,R).fi>= D) c++;
    else c--;
  }
  return max(1,(c+1)/2);
}
#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...