제출 #683348

#제출 시각아이디문제언어결과실행 시간메모리
683348TimDee송신탑 (IOI22_towers)C++17
60 / 100
1536 ms5816 KiB
#include "towers.h"
#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i=0;i<n;++i)

struct minsgt {
    vector<int> t;
    int n, sz;
    int merge(int x, int y) {
      return min(x,y);
    }
    void build(int v, int l, int r) {
        if (r-l==1) return;
        int m=(l+r)>>1;
        build(2*v+1,l,m);
        build(2*v+2,m,r);
        t[v]=merge(t[2*v+1],t[2*v+2]);
    }
    minsgt(vector<int>&a) {
        n=a.size();
        sz=1;
        while (sz<n) sz<<=1;
        t.assign(2*sz-1,1e9+7);
        forn(i,n) t[sz-1+i]=a[i];
        build(0,0,sz);
    }
    int query(int v, int l, int r, int lx, int rx) {
        if (r<=lx || l>=rx) return 1e9+7;
        if (lx<=l && r<=rx) return t[v];
        int m=(l+r)>>1;
        int L=query(2*v+1,l,m,lx,rx);
        int R=query(2*v+2,m,r,lx,rx);
        return merge(L,R);
    }
    int query(int l, int r) {
        return query(0,0,sz,l,r);
    }
};

struct maxsgt {
    vector<int> t;
    int n, sz;
    int merge(int x, int y) {
      return max(x,y);
    }
    void build(int v, int l, int r) {
        if (r-l==1) return;
        int m=(l+r)>>1;
        build(2*v+1,l,m);
        build(2*v+2,m,r);
        t[v]=merge(t[2*v+1],t[2*v+2]);
    }
    maxsgt(vector<int>&a) {
        n=a.size();
        sz=1;
        while (sz<n) sz<<=1;
        t.assign(2*sz-1,0);
        forn(i,n) t[sz-1+i]=a[i];
        build(0,0,sz);
    }
    int query(int v, int l, int r, int lx, int rx) {
        if (r<=lx || l>=rx) return 0;
        if (lx<=l && r<=rx) return t[v];
        int m=(l+r)>>1;
        int L=query(2*v+1,l,m,lx,rx);
        int R=query(2*v+2,m,r,lx,rx);
        return merge(L,R);
    }
    int query(int l, int r) {
        return query(0,0,sz,l,r);
    }
};

int n;
vector<int> h;
int paiu=1;
int pos=0,mx;
int D=-1;
int Q=0;
vector<int> pr(1e5+3,0);
void init(int N, vector<int> H) {
  n=N, h=H;
  forn(i,n) {
    if (h[i]>h[pos]) {
      pos=i;
    }
  }
  mx=h[pos];
  for(int i=pos-1; i+1; --i) paiu&=h[i+1]>h[i];
  for(int i=pos+1; i<n; ++i) paiu&=h[i-1]>h[i];

  pr[1]=h[0]<h[1];
  for (int i=1; i<n-1; ++i) {
    pr[i+1]=pr[i]+((h[i]<h[i-1])&&(h[i]<h[i+1]));
  }
  pr[n]=pr[n-1]+(h[n-1]<h[n-2]);
}

minsgt minst(pr);
maxsgt maxst(pr);
vector<int> nxt(1e5+3,0);
vector<int> jump(1e5+3,0);
int sq;
void build() {

  minst = minsgt(h);
  maxst = maxsgt(h);
  vector<int> less(n+1,n);
  forn(i,n) {
    int l=i, r=n;
    while (l<r) {
      int m=(l+r)>>1;
      int x=minst.query(i,m+1);
      if (h[i]-x>=D) r=m;
      else l=m+1;
    }
    less[i]=r;
  }
  for (int i=n-2; i+1; --i) less[i]=min(less[i],less[i+1]);
  vector<int> greater(n+1,n);
  forn(i,n) {
    int l=i, r=n;
    while (l<r) {
      int m=(l+r)>>1;
      int x=maxst.query(i,m+1);
      if (x-h[i]>=D) r=m;
      else l=m+1;
    }
    greater[i]=r;
  }
  for (int i=n-2; i+1; --i) {
    greater[i]=min(greater[i],greater[i+1]);
  }
  for (int i=n-1; i+1; --i) {
    nxt[i]=less[greater[i]];
  }

  sq = sqrt(n);
  for (int i=0; i<n; ++i) {
    int p=i;
    for (int cnt=0; cnt<sq; ++cnt) {
      if (p>=n) {
        break;
      }
      p=nxt[p];
    }
    jump[i]=p;
  }
  nxt[n]=jump[n]=n;
}

int max_towers(int l, int r, int d) {
  if (n==1) return 1;
  if (paiu) {
    if (r<=pos || l>=pos) return 1;
    int L=h[l], R=h[r];
    return 1+(max(L,R) <= mx-d);
  }
  ++Q;
  if (Q>=2) {
    if (D==-1) {
      D=d;
      build();
    }
    //forn(i,n+1) cout<<nxt[i]<<' '; cout<<'\n';
    //forn(i,n+1) cout<<jump[i]<<' '; cout<<'\n';
    int ans=0;
    int i=l;
    while (jump[i+1]<=r) {
      //cout<<"j"<<i<<' ';
      i=jump[i];
      ans+=sq;
    }
    while (i<=r) {
      //cout<<"ok"<<i<<' ';
      i=nxt[i];
      ans++;
    } 
    //cout<<"~"<<i<<' ';
    return max(ans,1);
  }
  vector<int> ans = {h[l]};
  for (int i=l+1; i<=r; ++i) {
    if (ans.size()&1) {
      if (h[i]<ans.back()) {
        ans[ans.size()-1]=h[i];
      } else if (h[i]-d>=ans.back()) ans.push_back(h[i]);
    } else {
      if (h[i]>ans.back()) {
        ans[ans.size()-1]=h[i];
      } else if (h[i]+d<=ans.back()) ans.push_back(h[i]);
    }
  }
  return (ans.size()+1)>>1;
}

int old(int l, int r, int d) {
  vector<int> ans = {h[l]};
  for (int i=l+1; i<=r; ++i) {
    if (ans.size()&1) {
      if (h[i]<ans.back()) {
        ans[ans.size()-1]=h[i];
      } else if (h[i]-d>=ans.back()) ans.push_back(h[i]);
    } else {
      if (h[i]>ans.back()) {
        ans[ans.size()-1]=h[i];
      } else if (h[i]+d<=ans.back()) ans.push_back(h[i]);
    }
  }
  return (ans.size()+1)>>1;
}
#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...