Submission #1348707

#TimeUsernameProblemLanguageResultExecution timeMemory
1348707SmuggingSpunTower (JOI24_tower)C++20
100 / 100
719 ms406292 KiB
#include<bits/stdc++.h>
#define taskname "C"
using namespace std;
typedef long long ll;
template<class T>void minimize(T& a, T b){
  if(a > b){
    a = b;
  }
}
const int lim = 2e5 + 36;
const ll INF = 1e18 + 36;
int n, q, a, b;
ll d, l[lim], r[lim], x[lim];
namespace sub1{
  const int LIM = 1e6 + 36;
  ll ans[LIM];
  bitset<LIM>can;  
  void solve(){
    can.set();
    for(int i = 1; i <= n; i++){
      for(int j = l[i]; j <= r[i]; j++){
        can[j] = false;
      }
    }
    memset(ans, 0x0f, sizeof(ans));
    ans[0] = 0;
    for(int i = 1; i < LIM; i++){
      if(can[i]){
        ans[i] = min(ans[i - 1] + a, (i >= d ? ans[i - d] : INF) + b);
      }
    }
    for(int i = 1; i <= q; i++){
      cout << (ans[x[i]] > INF ? -1 : ans[x[i]]) << "\n";
    }
  }
}
const ll LIM = 1e12 + 36;
struct Node{
  bool data, lazy;
  int lc, rc;
  Node(){
    data = lazy = false;
    lc = rc = -1;
  }
};
vector<Node>st(1);
void new_node(int id){
  if(st[id].lc == -1){
    st[id].lc = st.size();
    st.push_back(Node());
  }
  if(st[id].rc == -1){
    st[id].rc = st.size();
    st.push_back(Node());
  }
}
void push_down(int id){
  if(st[id].lazy){
    st[st[id].lc].data = st[st[id].lc].lazy = st[st[id].rc].data = st[st[id].rc].lazy = true;
    st[id].lazy = false;
  }
}
void update(int id, ll l, ll r, ll u, ll v){
  if(l > v || r < u){
    return;
  }
  st[id].data = true;
  if(u <= l && v >= r){
    st[id].lazy = true;
    return;
  }
  new_node(id);
  push_down(id);
  ll m = (l + r) >> 1LL;
  update(st[id].lc, l, m, u, v);
  update(st[id].rc, m + 1, r, u, v);
}
ll walk(int id, ll l, ll r, ll u, ll v){
  if(l > v){
    return l;
  }
  if(r < u || !st[id].data){
    return r + 1;
  }
  if(l == r){
    return l;
  }
  new_node(id);
  push_down(id);
  ll m = (l + r) >> 1LL, x = walk(st[id].lc, l, m, u, v);
  return x <= m ? x : walk(st[id].rc, m + 1, r, u, v);
}
bool is_on(ll p){
  int id = 0;
  ll l = 0, r = LIM;
  while(l < r){
    new_node(id);
    push_down(id);
    ll m = (l + r) >> 1LL;
    if(m < p){
      id = st[id].rc;
      l = m + 1;
    }
    else{
      id = st[id].lc;
      r = m;
    }
  }
  return st[id].data;
}
namespace sub2{
  void solve(){
    vector<pair<ll, ll>>range, new_range;
    range.push_back(make_pair(0, l[1] - 1));
    for(int i = 1; i < n; i++){
      range.push_back(make_pair(r[i] + 1, l[i + 1] - 1));
    }
    range.push_back(make_pair(r[n] + 1, LIM));
    update(0, 0, LIM, 0, 0);
    for(auto& [u, v] : range){
      ll x = walk(0, 0, LIM, u, v);
      if(x <= v){
        new_range.push_back(make_pair(x, v));
        if(x + d <= LIM){
          update(0, 0, LIM, x + d, min(LIM, v + d));
        }
        update(0, 0, LIM, x, v);
      }
    }
    swap(range, new_range);
    bool need_min_jump = b > d * a;
    for(int i = 1; i <= q; i++){
      auto it = prev(upper_bound(range.begin(), range.end(), make_pair(x[i], LIM)));
      if(it->second < x[i]){
        cout << "-1\n";
        continue;
      }
      if(need_min_jump){
        int cnt = 0;
        ll start = x[i];
        while(start > 0){
          auto it = prev(upper_bound(range.begin(), range.end(), make_pair(start, LIM)));
          if(it->first == 0){
            break;
          }
          start = it->first - d;
          cnt++;
        }
        cout << ll(b) * cnt + (x[i] - d * cnt) * a << "\n";
      }
      else{
        ll cnt = 0, start = x[i];
        while(start > 0){
          auto it = prev(upper_bound(range.begin(), range.end(), make_pair(start, LIM)));
          cnt += (start - it->first) / d;
          if(it->first == 0){
            break;
          }
          ll next_start = start - ((start - it->first) / d + 1) * d;
          it = prev(upper_bound(range.begin(), range.end(), make_pair(next_start, LIM)));
          start = min(next_start, prev(upper_bound(range.begin(), range.end(), make_pair(next_start, LIM)))->second);
          cnt++;
        }
        cout << b * cnt + (x[i] - d * cnt) * a << "\n";
      }
    }
  }
}
namespace sub3{
  void solve(){
    vector<pair<ll, ll>>range;
    range.push_back(make_pair(0, l[1] - 1));
    for(int i = 1; i < n; i++){
      range.push_back(make_pair(r[i] + 1, l[i + 1] - 1));
    }
    range.push_back(make_pair(r[n] + 1, LIM));
    update(0, 0, LIM, 0, 0);
    for(auto& [u, v] : range){
      ll x = walk(0, 0, LIM, u, v);
      if(x <= v){
        if(x + d <= LIM){
          update(0, 0, LIM, x + d, min(LIM, v + d));
        }
        update(0, 0, LIM, x, v);
      }
    }
    for(int i = 1; i <= q; i++){
      auto it = prev(upper_bound(range.begin(), range.end(), make_pair(x[i], LIM + 1)));
      cout << (it->second >= x[i] && is_on(x[i]) ? x[i] : -1) << "\n";
    }
  }
}
namespace sub4{
  vector<pair<ll, ll>>range, new_range;
  void solve_min_jump(){
    vector<int>dp(range.size());
    dp[0] = 0;
    for(int i = 1; i < range.size(); i++){
      dp[i] = dp[upper_bound(range.begin(), range.end(), make_pair(range[i].first - d, LIM)) - range.begin() - 1] + 1;
    } 
    for(int i = 1; i <= q; i++){
      auto it = prev(upper_bound(range.begin(), range.end(), make_pair(x[i], LIM)));
      if(it->second < x[i]){
        cout << "-1\n";
        continue;
      }
      int cnt = dp[upper_bound(range.begin(), range.end(), make_pair(x[i], LIM)) - range.begin() - 1];
      cout << ll(b) * cnt + (x[i] - d * cnt) * a << "\n";
    }
  }
  void solve_max_jump(){
    vector<pair<ll, ll>>ans;
    for(ll start = 0, cur = 0; true; ){
      ans.push_back(make_pair(start, cur));
      if(start >= range.back().first){
        break;
      }
      int sid = upper_bound(range.begin(), range.end(), make_pair(start, LIM)) - range.begin() - 1;
      cur += (range[sid].second - start) / d + 1;
      if((start += ((range[sid].second - start) / d + 1) * d) > range.back().second){
        break;
      }
      if(range[sid = upper_bound(range.begin(), range.end(), make_pair(start, LIM)) - range.begin() - 1].second < start){
        start = range[sid + 1].first;
      }
    }
    for(int i = 1; i <= q; i++){
      auto it = prev(upper_bound(range.begin(), range.end(), make_pair(x[i], LIM)));
      if(it->second < x[i]){
        cout << "-1\n";
        continue;
      }
      pair<ll, ll>val = *prev(upper_bound(ans.begin(), ans.end(), make_pair(x[i], LIM)));
      ll cnt = val.second + (x[i] - val.first) / d;
      cout << b * cnt + (x[i] - d * cnt) * a << "\n";
    }
  }
  void solve(){
    range.push_back(make_pair(0, l[1] - 1));
    for(int i = 1; i < n; i++){
      range.push_back(make_pair(r[i] + 1, l[i + 1] - 1));
    }
    range.push_back(make_pair(r[n] + 1, LIM));
    update(0, 0, LIM, 0, 0);
    for(auto& [u, v] : range){
      ll x = walk(0, 0, LIM, u, v);
      if(x <= v){
        new_range.push_back(make_pair(x, v));
        if(x + d <= LIM){
          update(0, 0, LIM, x + d, min(LIM, v + d));
        }
        update(0, 0, LIM, x, v);
      }
    }
    swap(range, new_range);
    bool need_min_jump = b > d * a;
    if(b > d * a){
      solve_min_jump();
    }
    else{
      solve_max_jump();
    }
  }
}
int main(){
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	if(fopen(taskname".inp", "r")){
		freopen(taskname".inp", "r", stdin);
	}
  cin >> n >> q >> d >> a >> b;
  for(int i = 1; i <= n; i++){
    cin >> l[i] >> r[i];
  }
  for(int i = 1; i <= q; i++){
    cin >> x[i];
  }
  if(max(r[n], *max_element(x + 1, x + q + 1)) <= 1000000){
    sub1::solve();
  }
  else if(max(n, q) <= 2000){
    sub2::solve();
  }
  else if(a == 1 && b == d){
    sub3::solve();
  }
  else{
    sub4::solve();
  }
}

Compilation message (stderr)

Main.cpp: In function 'int main()':
Main.cpp:268:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  268 |                 freopen(taskname".inp", "r", stdin);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...