Submission #1214430

#TimeUsernameProblemLanguageResultExecution timeMemory
1214430abczz수확 (JOI20_harvest)C++20
25 / 100
418 ms243468 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <array>
#include <map>
#include <queue>
#define ll long long

using namespace std;

random_device rd;
mt19937 mt(rd());
queue <ll> Q;
ll rnd() {return mt() % (ll)1e9; }

array<ll, 3> operator+(array<ll, 3> a, array<ll, 3> b) {
  return {a[0]+b[0], a[1]+b[1], a[2]+b[2]};
};
struct Treap{
  ll root;
  struct Node { ll v = -1, p = -1, sz = 1, l = 0, r = 0; };
  vector <Node> node = {{-1, -1, 0, 0, 0}};
  void split_lb(ll treap, ll &l, ll &r, ll x) {
    if (!treap) {
      l = r = 0;
      return;
    }
    auto &N = node[treap];
    if (N.v < x) {
      split_lb(N.r, N.r, r, x);
      l = treap;
    }
    else {
      split_lb(N.l, l, N.l, x);
      r = treap;
    }
    N.sz = node[N.l].sz + node[N.r].sz + 1;
  }
  void split_sz(ll treap, ll &l, ll &r, ll x) {
    if (!treap) {
      l = r = 0;
      return;
    }
    auto &N = node[treap];
    if (x <= node[N.l].sz) {
      split_sz(N.l, l, N.l, x);
      r = treap;
    }
    else {
      split_sz(N.r, N.r, r, x-node[N.l].sz-1);
      l = treap;
    }
    N.sz = node[N.l].sz + node[N.r].sz + 1;
  }
  void merge(ll &treap, ll l, ll r) {
    if (!l) {
      treap = r;
      return;
    }
    if (!r) {
      treap = l;
      return;
    }
    if (node[l].p < node[r].p) {
      merge(node[l].r, node[l].r, r);
      treap = l;
    }
    else {
      merge(node[r].l, l, node[r].l);
      treap = r;
    }
    auto &N = node[treap];
    N.sz = node[N.l].sz + node[N.r].sz + 1;
  }
  void insert(ll &treap, ll t) {
    if (!treap) {
      treap = t;
      return;
    }
    auto &N = node[treap];
    if (N.p < node[t].p) {
      if (N.v < node[t].v) insert(N.r, t);
      else insert(N.l, t);
      N.sz = node[N.l].sz + node[N.r].sz + 1;
    }
    else {
      split_lb(treap, node[t].l, node[t].r, node[t].v);
      treap = t;
      node[t].sz = node[node[t].l].sz + node[node[t].r].sz + 1;
    }
  }
  ll query(ll treap, ll x) {
    if (!treap) return 0;
    auto N = node[treap];
    if (N.v < x) return node[N.l].sz + 1 + query(N.r, x);
    else return query(N.l, x);
  }
  void addNode(ll w) {
    node.push_back({w, rnd(), 1, 0, 0});
    if (node.size() == 2) root = 1;
    else insert(root, node.size()-1);
  }
  void delNode(ll w) {
    ll t1, t2, t3;
    split_lb(root, t1, t2, w);
    split_sz(t2, t2, t3, 1);
    merge(root, t1, t3);
  }
  void clear() {
    node = {{-1, -1, 0, 0, 0}};
    root = 0;
  }
}T[400000];
ll cyc_len, s;
struct SegTree{
  Treap st[800000];
  ll sum[800000], cnt[800000];
  vector <ll> X;
  void init(ll sz) {
    for (int i=0; i<4*sz; ++i) {
      sum[i] = cnt[i] = 0;
      st[i].clear();
    }
  }
  void insert(ll id, ll l, ll r, ll q, ll w) {
    st[id].addNode(w);
    if (l == r) {
      sum[id] += (X[l] >= 0 ? X[l] / cyc_len : (X[l]-cyc_len+1)/cyc_len), ++cnt[id];
      return;
    }
    ll mid = (l+r)/2;
    if (q <= X[mid]) insert(id*2, l, mid, q, w);
    else insert(id*2+1, mid+1, r, q, w);
    sum[id] = sum[id*2] + sum[id*2+1];
    cnt[id] = cnt[id*2] + cnt[id*2+1];
  }
  void del(ll id, ll l, ll r, ll q, ll w) {
    st[id].delNode(w);
    if (l == r) {
      sum[id] -= (X[l] >= 0 ? X[l] / cyc_len : (X[l]-cyc_len+1)/cyc_len), --cnt[id];
      return;
    }
    ll mid = (l+r)/2;
    if (q <= X[mid]) del(id*2, l, mid, q, w);
    else del(id*2+1, mid+1, r, q, w);
    sum[id] = sum[id*2] + sum[id*2+1];
    cnt[id] = cnt[id*2] + cnt[id*2+1];
  }
  array<ll, 3> query(ll id, ll l, ll r, ll q, ll w) {
    if (q < X[l]) return {0, 0, 0};
    if (q >= X[r]) return {st[id].query(st[id].root, w), sum[id], cnt[id]};
    ll mid = (l+r)/2;
    return query(id*2, l, mid, q, w) + query(id*2+1, mid+1, r, q, w);
  }
  void clear() {
    X.clear();
  }
}ST;
ll n, m, l, c, q;
map <ll, ll> mp;
vector <array<ll, 2>> query[400000];
vector <ll> adj[400000];
ll A[200000], B[200000], P[400000], W[400000], in[400000], sz[400000], delta[400000];
ll a, b, F[200000];

void bfs(ll u) {
  ll mx = -1, id = -1;
  for (auto v : adj[u]) {
    if (sz[v] > mx) mx = sz[v], id = v;
  }
  if (id != -1) {
    delta[u] = delta[id] + W[id];
    swap(T[u], T[id]);
  }
  for (auto v : adj[u]) {
    if (v == id) continue;
    for (int j=1; j<T[v].node.size(); ++j) {
      T[u].addNode(T[v].node[j].v+delta[v]+W[v]-delta[u]);
    }
  }
  if (u >= n) T[u].addNode(0);
}

ll prev(ll u) {
  u %= l;
  if (u < 0) u += l;
  if (u < A[0]) u += (ll)((A[0]-u+l-1)/l) * l;
  return lower_bound(A, A+n, u+1)-A-1;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cin >> n >> m >> l >> c;
  for (int i=0; i<n; ++i) cin >> A[i];
  for (int i=0; i<m; ++i) cin >> B[i];
  cin >> q;
  for (int i=0; i<q; ++i) {
    cin >> a >> b;
    --a;
    query[a].push_back({b, i});
  }
  for (int i=0; i<m; ++i) P[n+i] = prev(B[i]), W[n+i] = (B[i]-A[P[n+i]]+l) % l, ++in[P[n+i]];
  for (int i=0; i<n; ++i) {
    P[i] = prev(A[i]-c), ++in[P[i]];
    ll k = ((A[i]-A[P[i]]+l)%l);
    if (k < c) k += (ll)((c-k+l-1)/l) * l;
    W[i] = k;
  }
  for (int i=0; i<n+m; ++i) {
    sz[i] = 1;
    if (!in[i]) Q.push(i);
  }
  while (!Q.empty()) {
    auto u = Q.front();
    Q.pop();
    bfs(u);
    for (auto [x, id] : query[u]) {
      F[id] = T[u].query(T[u].root, x-delta[u]+1);
    }
    --in[P[u]];
    adj[P[u]].push_back(u);
    sz[P[u]] += sz[u];
    if (!in[P[u]]) Q.push(P[u]);
  }
  for (int i=0; i<n; ++i) {
    if (!in[i]) continue;
    ST.clear();
    mp.clear();
    ll u = i;
    cyc_len = 0, s = 0;
    while (true) {
      cyc_len += W[u];
      in[u] = 0;
      bfs(u);
      u = P[u];
      if (u == i) break;
    }
    while (true) {
      for (int j=1; j<T[u].node.size(); ++j) {
        ++mp[T[u].node[j].v+s+delta[u]];
        ++mp[T[u].node[j].v-cyc_len+s+delta[u]];
      }
      (s += (cyc_len-W[u])) %= cyc_len;
      u = P[u];
      if (u == i) break;
    }
    for (auto [x, y] : mp) ST.X.push_back(x);
    if (ST.X.empty()) continue;
    ST.init(ST.X.size());
    s = 0;
    while (true) {
      for (int j=1; j<T[u].node.size(); ++j) {
        ST.insert(1, 0, ST.X.size()-1, T[u].node[j].v+s+delta[u], (T[u].node[j].v+s+delta[u]) % cyc_len);
      }
      (s += (cyc_len-W[u])) %= cyc_len;
      u = P[u];
      if (u == i) break;
    }
    s = 0;
    while (true) {
      ll dist = (cyc_len-s) % cyc_len;
      for (auto [x, id] : query[u]) {
        auto res1 = ST.query(1, 0, ST.X.size()-1, x-dist, (x % cyc_len)-dist+1);
        auto res2 = ST.query(1, 0, ST.X.size()-1, x-dist, ((x-dist+cyc_len) % cyc_len)+1);
        F[id] = res1[2] + res1[2] * (ll)(x-dist >= 0 ? ((x-dist)/cyc_len) : (x-dist-cyc_len+1)/cyc_len) - res1[1] - (res1[2] - res2[0]);
      }
      (s += (cyc_len-W[u])) %= cyc_len;
      u = P[u];
      if (u == i) break;
      for (int j=1; j<T[u].node.size(); ++j) {
        ST.del(1, 0, ST.X.size()-1, T[u].node[j].v+s+delta[u], (T[u].node[j].v+s+delta[u]) % cyc_len);
        ST.insert(1, 0, ST.X.size()-1, T[u].node[j].v-cyc_len+s+delta[u], (T[u].node[j].v+s+delta[u]) % cyc_len);
      }
    }
  }
  for (int i=0; i<q; ++i) cout << F[i] << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...