제출 #1328863

#제출 시각아이디문제언어결과실행 시간메모리
1328863SmuggingSpunMeetings (IOI18_meetings)C++20
100 / 100
3441 ms368404 KiB
#include "meetings.h"
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
template<class T>void minimize(T& a, T b){
  if(a > b){
    a = b;
  }
}
template<class T>void maximize(T& a, T b){
  if(a < b){
    a = b;
  }
}
int n, q;
vector<pair<int, int>>query;
vector<int>a;
namespace sub12{
  vector<ll>solve(){
    vector<vector<ll>>f(n + 1, vector<ll>(n + 1));
    for(int i = 1; i <= n; i++){
      f[i][0] = 0;
      for(int j = 1; j < i; j++){
        f[i][j] += f[i][j - 1];
      }
      for(int j = i, x = 0; j <= n; j++){
        maximize(x, a[j]);
        f[i][j] = f[j][i] = x;
        f[i][j] += f[i][j - 1];
      }
    }
    vector<ll>ans;
    for(auto& [l, r] : query){
      ll cur = INF;
      for(int i = l; i <= r; i++){
        minimize(cur, f[i][r] - f[i][l - 1]);
      }
      ans.push_back(cur);
    }
    return ans;
  }
}
namespace sub3{
  struct Node{
    int len, pf, sf, opt;
    Node(){
      len = pf = sf = opt = 0;
    }
  };
  Node merge(Node a, Node b){
    Node c;
    c.len = a.len + b.len;
    c.pf = a.pf == a.len ? a.pf + b.pf : a.pf;
    c.sf = b.sf == b.len ? b.sf + a.sf : b.sf;
    c.opt = max({a.opt, b.opt, a.sf + b.pf});
    return c;
  }
  vector<ll>solve(){
    vector<Node>st(n << 2 | 3);
    function<void(int, int, int)>build;
    build = [&] (int id, int l, int r){
      if(l == r){
        st[id].pf = st[id].sf = st[id].opt = a[l] & (st[id].len = 1);
        return;
      }
      int m = (l + r) >> 1;
      build(id << 1, l, m);
      build(id << 1 | 1, m + 1, r);
      st[id] = merge(st[id << 1], st[id << 1 | 1]);
    };
    build(1, 1, n);
    function<Node(int, int, int, int, int)>get;
    get = [&] (int id, int l, int r, int u, int v){
      if(l > v || r < u){
        return Node();
      }
      if(u <= l && v >= r){
        return st[id];
      }
      int m = (l + r) >> 1;
      return merge(get(id << 1, l, m, u, v), get(id << 1 | 1, m + 1, r, u, v));
    };
    vector<ll>ans;
    for(auto& [l, r] : query){
      ans.push_back(((r - l + 1) << 1) - get(1, 1, n, l, r).opt);
    }
    return ans;
  }
}
namespace sub4{
  struct Node{
    int l, r, m, lc, rc;
    ll v;
    Node(){}
  };
  vector<Node>st(1);
  int build(int l, int r){
    if(l > r){
      return 0;
    }
    int id = st.size();
    st.push_back(Node());
    st[id].l = l;
    st[id].r = r;
    if(l < r){
      int mx = *max_element(a.begin() + l, a.begin() + r + 1);
      vector<int>p;
      for(int i = l; i <= r; i++){
        if(a[i] == mx){
          p.push_back(i);
        }
      }
      st[id].m = p[int(p.size()) >> 1];
      st[id].v = min(st[st[id].lc = build(l, st[id].m - 1)].v + ll(mx) * (r - st[id].m + 1), st[st[id].rc = build(st[id].m + 1, r)].v + ll(mx) * (st[id].m - l + 1));
    }
    else{
      st[id].v = a[l];
    }
    return id;
  }
  int overlap(int l1, int r1, int l2, int r2){
    return max(0, min(r1, r2) - max(l1, l2) + 1);
  }
  ll get(int id, int u, int v){
    if(st[id].l > v || st[id].r < u){
      return 0;
    }
    if(u <= st[id].l && v >= st[id].r){
      return st[id].v;
    }
    return min(get(st[id].lc, u, v) + ll(a[st[id].m]) * overlap(st[id].m, st[id].r, u, v), get(st[id].rc, u, v) + ll(a[st[id].m]) * overlap(st[id].l, st[id].m, u, v));
  }
  vector<ll>solve(){
    build(1, n);
    vector<ll>ans;
    for(auto& [l, r] : query){
      ans.push_back(get(1, l, r));
    }
    return ans;
  }
}
namespace sub5{
  const int lim = 75e4 + 5;
  int lgv[lim], spt[20][lim];
  bool flag = false;
  struct Node{
    int l, r, p, lc, rc;
    Node(){
      lc = rc = -1;
    }
  };
  int max_index(int i, int j){
    if((!flag && i > j) || (flag && i < j)){
      swap(i, j);
    }
    return a[i] > a[j] ? i : j;
  }
  int get_max_pos(int l, int r){
    int k = lgv[r - l + 1];
    return max_index(spt[k][l], spt[k][r - (1 << k) + 1]);
  }
  vector<Node>st;
  int build(int l, int r){
    if(l > r){
      return -1;
    }
    int id = st.size();
    st.push_back(Node());
    st[id].lc = build(l, (st[id].p = get_max_pos(st[id].l = l, st[id].r = r)) - 1);
    st[id].rc = build(st[id].p + 1, r);
    return id;
  }
  vector<int>event[lim];
  vector<ll>ans;
  struct SegmentTree{
    ll st[lim << 2], lazy[lim << 2];
    bitset<lim << 2>mark;
    void init(){
      memset(st, 0, sizeof(st));
      memset(lazy, 0, sizeof(lazy));
      mark.reset();
    }
    void propagate(int id, ll x){
      st[id] += x;
      lazy[id] += x;
    }
    void push_down(int id){
      if(mark[id]){
        mark[id << 1] = mark[id << 1 | 1] = true;
        st[id << 1] = st[id << 1 | 1] = lazy[id << 1] = lazy[id << 1 | 1] = 0;
        mark[id] = false;
      }
      propagate(id << 1, lazy[id]);
      propagate(id << 1 | 1, lazy[id]);
      lazy[id] = 0;
    }
    void update(int id, int l, int r, int u, int v, ll x){
      if(l > v || r < u){
        return;
      }
      if(u <= l && v >= r){
        propagate(id, x);
        return;
      }
      int m = (l + r) >> 1;
      push_down(id);
      update(id << 1, l, m, u, v, x);
      update(id << 1 | 1, m + 1, r, u, v, x);
      st[id] = st[id << 1 | 1];
    }
    void fill_zero(int id, int l, int r, int u, int v){
      if(l > v || r < u){
        return;
      }
      if(u <= l && v >= r){
        mark[id] = true;
        st[id] = lazy[id] = 0;
        return;
      }
      int m = (l + r) >> 1;
      push_down(id);
      fill_zero(id << 1, l, m, u, v);
      fill_zero(id << 1 | 1, m + 1, r, u, v);
      st[id] = st[id << 1 | 1];
    }
    ll get(int p){
      int id = 1, l = 0, r = n;
      while(l < r){
        int m = (l + r) >> 1;
        push_down(id);
        id <<= 1;
        if(m < p){
          id |= 1;
          l = m + 1;
        }
        else{
          r = m;
        }
      }
      return st[id];
    }
  };
  struct SegmentTreeLine{
    SegmentTree a, b;
    void init(){
      a.init();
      b.init();
    }
    void update(int u, int v, pair<int, ll>line){
      a.update(1, 0, n, u, v, line.first);
      b.update(1, 0, n, u, v, line.second - ll(u) * line.first);
    }
    void fill_zero(int u, int v){
      a.fill_zero(1, 0, n, u, v);
      b.fill_zero(1, 0, n, u, v);
    }
    ll get(int p){
      return a.get(p) * p + b.get(p);
    }
    int walk(int id, int l, int r, int u, int v, int mx, ll f, ll g){
      if(r < u){
        return r;
      }
      if(l > v){
        return l - 1;
      }
      if(u <= l && v >= r && f + ll(mx) * (r - u + 1) < g + a.st[id] * r + b.st[id]){
        return r;
      }
      if(l == r){
        return l - 1;
      }
      int m = (l + r) >> 1;
      a.push_down(id);
      b.push_down(id);
      int left = walk(id << 1, l, m, u, v, mx, f, g);
      return left == m ? walk(id << 1 | 1, m + 1, r, u, v, mx, f, g) : left;
    }
  };
  SegmentTreeLine val;
  void dfs(int id){
    if(st[id].lc != -1){
      dfs(st[id].lc);
    }
    if(st[id].rc != -1){
      dfs(st[id].rc);
    }
    val.update(st[id].p, st[id].p, make_pair(0, val.get(st[id].p - 1) + a[st[id].p]));
    if(st[id].rc != -1){
      int pos = val.walk(1, 0, n, st[id].p + 1, st[id].r, a[st[id].p], val.get(st[id].p), ll(st[id].p - st[id].l + 1) * a[st[id].p]);
      val.fill_zero(st[id].p + 1, pos);
      val.update(st[id].p + 1, pos, make_pair(a[st[id].p], val.get(st[id].p) + a[st[id].p]));
      val.update(pos + 1, st[id].r, make_pair(0, ll(st[id].p - st[id].l + 1) * a[st[id].p]));
    }
    for(int& i : event[st[id].p]){
      minimize(ans[i], val.get(query[i].second) + ll(st[id].l - query[i].first) * a[st[id].l - 1]);
    }
  }
  void play(){
    for(int i = 1; i < 20; i++){
      for(int j = 1; j + (1 << i) - 1 <= n; j++){
        spt[i][j] = max_index(spt[i - 1][j], spt[i - 1][j + (1 << (i - 1))]);
      }
    }
    for(int i = 1; i <= n; i++){
      event[i].clear();
    }
    for(int i = 0; i < q; i++){
      auto& [l, r] = query[i];
      int p = get_max_pos(l, r);
      if(p < r){
        event[get_max_pos(p + 1, r)].push_back(i);
      }
      else{
        minimize(ans[i], ll(a[p]) * (r - l + 1));
      }
    }
    val.init();
    st.clear();
    dfs(build(1, n));
  }
  vector<ll>solve(){
    lgv[0] = -1;
    for(int i = 1; i <= n; i++){
      lgv[spt[0][i] = i] = lgv[i >> 1] + 1;
    }
    ans.assign(q, INF);
    play();
    flag = true;
    reverse(a.begin() + 1, a.end());
    for(auto& [l, r] : query){
      swap(l = n - l + 1, r = n - r + 1);
    }
    play();
    return ans;
  }
}
vector<ll>minimum_costs(vector<int>H, vector<int>L, vector<int>R) {
  q = L.size();
  for(int i = 0; i < q; i++){
    query.push_back(make_pair(L[i] + 1, R[i] + 1));
  }
  swap(a, H);
  n = a.size();
  a.insert(a.begin(), 0);
  if(max(n, q) <= 5000){
    return sub12::solve();
  }
  if(*max_element(a.begin() + 1, a.end()) <= 2){
    return sub3::solve();
  }
  if(max(n, q) <= 100000 && *max_element(a.begin() + 1, a.end()) <= 20){
    return sub4::solve();
  }
  return sub5::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...