Submission #1013529

# Submission time Handle Problem Language Result Execution time Memory
1013529 2024-07-03T15:29:46 Z spacewalker Ideal city (IOI12_city) C++14
Compilation error
0 ms 0 KB
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
constexpr ll MOD = 1'000'000'000;

struct Segment {
  int x, y1, y2;
  Segment(int x, int y1, int y2) : x(x), y1(y1), y2(y2) {}
};

ostream& operator << (ostream& os, const Segment &s) {
  return os << "[x = " << s.x << "; y = " << s.y1 << "..." << s.y2 << "]";
}

bool adjacent(const Segment &a, const Segment &b) {
  return abs(a.x - b.x) <= 1 && max(a.y1, b.y1) <= min(a.y2, b.y2); 
}

vector<Segment> divide_into_segments(const vector<pair<int, int>> &blocks) {
  vector<Segment> segments;
  optional<Segment> currentSegment;
  for (int i = 0; i < blocks.size(); ++i) {
    if (!currentSegment) currentSegment = Segment(blocks[i].first, blocks[i].second, blocks[i].second);
    else if (currentSegment->x != blocks[i].first || currentSegment->y2 + 1 < blocks[i].second) {
      segments.push_back(*currentSegment);
      currentSegment = Segment(blocks[i].first, blocks[i].second, blocks[i].second);
    } else {
      currentSegment->y2 = blocks[i].second;
    }
  }
  if (currentSegment) segments.push_back(*currentSegment);
  return segments;
}

ll pair_distance_sum(const vector<ll> &points) {
  if (points.size() == 0) {
    return 0;
  }
  ll ans = 0;
  ll total = accumulate(points.begin(), points.end(), 0LL);
  ll right_side = 0;
  for (int i = 0; i < points.size(); ++i) {
    right_side += points[i];
    ans += right_side * (total - right_side) % MOD;
  }
  /*
  cerr << "PDS " << ans;
  for (ll v : points) cerr << " " << v;
  cerr << endl;
  */
  return ans % MOD;
}

vector<vector<ll>> segments_reachable;

ll sum_of_distances(int n, const vector<vector<int>> &tree, const vector<Segment> &segs, int v, int p) {
  auto cseg = segs[v];
  int length = cseg.y2 - cseg.y1 + 1;
  segments_reachable[v].assign(length, 1);

  auto comp = [&] (int y) {
    return clamp(y, cseg.y1, cseg.y2) - cseg.y1;
  };

  ll ans = 0;
  for (int child : tree[v]) {
    if (child == p) continue;
    ans += sum_of_distances(n, tree, segs, child, v);
    int comp_min = comp(segs[child].y1), comp_max = comp(segs[child].y2);
    vector<ll> csubsegment(comp_max - comp_min + 1); 
    ll segments_in_child = accumulate(segments_reachable[child].begin(),
        segments_reachable[child].end(), 0LL);
    for (int y = segs[child].y1; y <= segs[child].y2; ++y) {
      ll segments_here = segments_reachable[child][y - segs[child].y1];
      segments_reachable[v][comp(y)] += segments_here;
      csubsegment[comp(y) - comp_min] += segments_here;

      ll delta_y = abs(y - clamp(y, cseg.y1, cseg.y2)) + 1;
      ans += delta_y * segments_here % MOD * (n - segments_in_child) % MOD;
    }
    ans -= pair_distance_sum(csubsegment);
  }
  ans += pair_distance_sum(segments_reachable[v]);
  ans = (ans % MOD + MOD) % MOD;
  // cerr << "SOD " << v << " (par " << p << " " << segs[v] << ") ans " << ans << endl;
  return ans;
}


int DistanceSum(int N, int *X, int *Y) {
  segments_reachable.assign(N, vector<ll>());
  vector<pair<int, int>> blocks(N);
  for (int i = 0; i < N; ++i) blocks[i] = {X[i], Y[i]};
  sort(blocks.begin(), blocks.end());
  auto segments = divide_into_segments(blocks);

  // for (auto &s : segments) cerr << s << endl;

  int k = segments.size();
  vector<vector<int>> tree(k);

  for (int i = 0, j = 0, prev = 0; i < k; prev = i, i = j) {
    while (j < k && segments[j].x == segments[i].x) ++j;
    int cprev = prev;
    for (int cseg_i = i; cseg_i < j; ++cseg_i) {
      while (cprev < i && segments[cprev].y2 < segments[cseg_i].y1) ++cprev;
      while (cprev < i && adjacent(segments[cseg_i], segments[cprev])) {
        // cerr << "adjacent " << segments[cseg_i] << " " << segments[cprev] << endl;
        tree[cseg_i].push_back(cprev);
        tree[cprev].push_back(cseg_i);
        if (segments[cprev].y2 <= segments[cseg_i].y1) {
          ++cprev;
        } else {
          break;
        }
      }
    }
  }

  return sum_of_distances(N, tree, segments, 0, -1); 
}

Compilation message

city.cpp: In function 'std::vector<Segment> divide_into_segments(const std::vector<std::pair<int, int> >&)':
city.cpp:23:3: error: 'optional' was not declared in this scope
   23 |   optional<Segment> currentSegment;
      |   ^~~~~~~~
city.cpp:23:3: note: 'std::optional' is only available from C++17 onwards
city.cpp:23:19: error: expected primary-expression before '>' token
   23 |   optional<Segment> currentSegment;
      |                   ^
city.cpp:23:21: error: 'currentSegment' was not declared in this scope
   23 |   optional<Segment> currentSegment;
      |                     ^~~~~~~~~~~~~~
city.cpp:24:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   24 |   for (int i = 0; i < blocks.size(); ++i) {
      |                   ~~^~~~~~~~~~~~~~~
city.cpp: In function 'll pair_distance_sum(const std::vector<long long int>&)':
city.cpp:44:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   44 |   for (int i = 0; i < points.size(); ++i) {
      |                   ~~^~~~~~~~~~~~~~~
city.cpp: In lambda function:
city.cpp:64:12: error: 'clamp' was not declared in this scope
   64 |     return clamp(y, cseg.y1, cseg.y2) - cseg.y1;
      |            ^~~~~
city.cpp: In function 'll sum_of_distances(int, const std::vector<std::vector<int> >&, const std::vector<Segment>&, int, int)':
city.cpp:72:28: error: 'comp_max' was not declared in this scope; did you mean 'comp_min'?
   72 |     vector<ll> csubsegment(comp_max - comp_min + 1);
      |                            ^~~~~~~~
      |                            comp_min
city.cpp:80:28: error: 'clamp' was not declared in this scope
   80 |       ll delta_y = abs(y - clamp(y, cseg.y1, cseg.y2)) + 1;
      |                            ^~~~~