답안 #659016

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
659016 2022-11-15T19:31:45 Z 600Mihnea 새 집 (APIO18_new_home) C++17
0 / 100
4 ms 7252 KB
bool home = 1;

#include <bits/stdc++.h>

using namespace std;

struct MinSegmentTree {
  vector<int> tree;
  int nn;
  void upd(int v, int tl, int tr, int i, int x) {
    if (tr < i || i < tl) {
      return;
    }
    if (tl == tr) {
      tree[v] = x;
      return;
    }
    int tm = (tl + tr) / 2;
    upd(2 * v, tl, tm, i, x);
    upd(2 * v + 1, tm + 1, tr, i, x);
    tree[v] = min(tree[2 * v], tree[2 * v + 1]);
  }
  int getmin(int v, int tl, int tr, int l, int r) {
    if (tr < l || r < tl) {
      return (int) 1e9 + 7;
    }
    if (l <= tl && tr <= r) {
      return tree[v];
    }
    int tm = (tl + tr) / 2;
    return min(getmin(2 * v, tl, tm, l, r), getmin(2 * v + 1, tm + 1, tr, l, r));
  }
  void init(int n) {
    nn = n;
    tree.clear();
    tree.resize(4 * (n + 7), (int) 1e9 + 7);
  }
  void upd(int i, int x) {
    upd(1, 0, nn - 1, i, x);
  }
  int getmin(int l, int r) {
    if (l > r) {
      return (int) 1e9 + 7;
    }
    return getmin(1, 0, nn - 1, l, r);
  }
};

struct Store {
  int x;
  int type;
  int first_time;
  int last_time;
};

struct Query {
  int x;
  int t;
};

const int N = (int) 3e5 + 7;
int n;
int k;
int q;
vector<int> whereType[N];
Store stores[N];
Query queries[N];
bool negative[N];
vector<int> events;

int getTimeOfEvent(int i) {
  if (i >= 1) {
    return stores[i].first_time;
  } else {
    i *= -1;
    return stores[i].last_time + 1;
  }
}

bool cmpEvents(int i, int j) {
  return getTimeOfEvent(i) < getTimeOfEvent(j);
}

struct Position {
  int i;
};

bool operator < (Position a, Position b) {
  int i = a.i, j = b.i;
  if (stores[i].x == stores[j].x) {
    return i < j;
  } else {
    return stores[i].x < stores[j].x;
  }
}

struct Segment {
  int first_time;
  int last_time;
  int x1;
  int x2;
};

struct RelaxSegment {
  int first_time;
  int last_time;
  int limit;
  int x;
};

vector<RelaxSegment> rels[2];

vector<Segment> segments;

void addSegment(int first_time, int last_time, int i, int j) {
  if (first_time > last_time) {
    return;
  }
  segments.push_back({first_time, last_time, stores[i].x, stores[j].x});
}

vector<RelaxSegment> relaxSegments;

int getTimeOfRelaxSegmentEvent(int i) {
  if (i >= 1) {
    i--;
    return relaxSegments[i].first_time;
  } else {
    i *= -1;
    i--;
    return relaxSegments[i].last_time + 1;
  }
}

bool cmpRelaxSegmentEvents(int i, int j) {
  return getTimeOfRelaxSegmentEvent(i) < getTimeOfRelaxSegmentEvent(j);
}

int print[N];
int small[N];

int main() {
  if (home) {
    freopen ("input.txt", "r", stdin);
  } else {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  }
  {
    /// Read
    cin >> n >> k >> q;
    for (int i = 1; i <= n; i++) {
      cin >> stores[i].x >> stores[i].type >> stores[i].first_time >> stores[i].last_time;
    }
    for (int i = 1; i <= q; i++) {
      cin >> queries[i].x >> queries[i].t;
    }
  }
  {
    /// Normalize time
    vector<int> interestingTimes;
    for (int i = 1; i <= q; i++) {
      interestingTimes.push_back(queries[i].t);
    }
    sort(interestingTimes.begin(), interestingTimes.end());
    interestingTimes.resize(unique(interestingTimes.begin(), interestingTimes.end()) - interestingTimes.begin());
    for (int i = 1; i <= q; i++) {
      queries[i].t = lower_bound(interestingTimes.begin(), interestingTimes.end(), queries[i].t) - interestingTimes.begin();
    }
    int y = 0;
    for (int i = 1; i <= n; i++) {
      stores[i].first_time = lower_bound(interestingTimes.begin(), interestingTimes.end(), stores[i].first_time) - interestingTimes.begin();
      stores[i].last_time = lower_bound(interestingTimes.begin(), interestingTimes.end(), stores[i].last_time + 1) - interestingTimes.begin() - 1;
      if (stores[i].first_time <= stores[i].last_time) {
        stores[++y] = stores[i];
      }
    }
    n = y;
  }

  {
    /// Some more computation
    for (int i = 1; i <= n; i++) {
      whereType[stores[i].type].push_back(i);
    }
    stores[n + 1].x = -((int) 1e8 + 7);
    stores[n + 2].x = +((int) 2e8 + 7);
    for (int type = 1; type <= k; type++) {
      set<Position> positions;
      map<pair<int, int>, int> sinceWhen;
      positions.insert({n + 1});
      positions.insert({n + 2});

      sinceWhen[{n + 1, n + 2}] = 0;
      events.clear();
      for (auto &i : whereType[type]) {
        events.push_back(+i);
        events.push_back(-i);
      }
      sort(events.begin(), events.end(), cmpEvents);
      int l_events = 0;
      while (l_events < (int) events.size()) {
        int r_events = l_events;
        while (r_events + 1 < (int) events.size() && getTimeOfEvent(events[r_events + 1]) == getTimeOfEvent(events[r_events])) {
          r_events++;
        }
        int current_time = getTimeOfEvent(events[l_events]);
        for (int iter_events = l_events; iter_events <= r_events; iter_events++) {
          int i = events[iter_events];

          if (i >= 1) {
            positions.insert({i});


            auto it = positions.find({i});
            auto nxt = it;
            auto ant = it;
            nxt++;
            ant--;

            addSegment(sinceWhen[{ant->i, nxt->i}], current_time - 1, ant->i, nxt->i);

            sinceWhen.erase({ant->i, nxt->i});
            sinceWhen[{ant->i, it->i}] = current_time;
            sinceWhen[{it->i, nxt->i}] = current_time;
          } else {
            i *= -1;

            auto it = positions.find({i});
            auto nxt = it;
            auto ant = it;
            nxt++;
            ant--;

            sinceWhen[{ant->i, nxt->i}] = current_time;


            addSegment(sinceWhen[{ant->i, it->i}], current_time - 1, ant->i, it->i);
            sinceWhen.erase({ant->i, it->i});

            addSegment(sinceWhen[{it->i, nxt->i}], current_time - 1, it->i, nxt->i);
            sinceWhen.erase({it->i, nxt->i});

            positions.erase({i});
          }
        }
        l_events = r_events + 1;
      }
      for (auto &it : sinceWhen) {
        addSegment(it.second, q - 1, it.first.first, it.first.second);
      }
    }
  }
  {
    /// Some other Brute

    for (auto &segment : segments) {
      int t1 = segment.first_time;
      int t2 = segment.last_time;
      int x1 = segment.x1;
      int x2 = segment.x2;

      int xmid = (x1 + x2) / 2;
      int xmid2 = (x1 + x2 + 1) / 2;
      rels[0].push_back({t1, t2, xmid, x1});
      rels[1].push_back({t1, t2, -xmid2, -x2});
    }

    for (int inv = 0; inv <= 1; inv++) {
      for (int iq = 1; iq <= q; iq++) {
        small[iq] = (int) 1e9 + 7;
      }
      relaxSegments = rels[inv];
      MinSegmentTree tree;
      tree.init((int) relaxSegments.size());

      sort(relaxSegments.begin(), relaxSegments.end(), [&] (RelaxSegment a, RelaxSegment b) {
        return a.limit > b.limit;
      });

      vector<int> relaxSegmentEvents;
      for (int i = 0; i < (int) relaxSegments.size(); i++) {
        relaxSegmentEvents.push_back((i + 1));
        relaxSegmentEvents.push_back(-(i + 1));
      }

      sort(relaxSegmentEvents.begin(), relaxSegmentEvents.end(), cmpRelaxSegmentEvents);
      int p = 0;
      vector<int> ord;
      for (int iq = 1; iq <= q; iq++) {
        ord.push_back(iq);
      }
      sort(ord.begin(), ord.end(), [&] (int i, int j) {
        return queries[i].t < queries[j].t;
      });
      for (auto &iq : ord) {
        while (p < (int) relaxSegmentEvents.size() && getTimeOfRelaxSegmentEvent(relaxSegmentEvents[p]) <= queries[iq].t) {
          int i = relaxSegmentEvents[p++];

          if (i >= 1) {
            i--;
            tree.upd(i, relaxSegments[i].x);
          } else {
            i *= -1;
            i--;
            tree.upd(i, (int) 1e9 + 7);
          }
        }
        int cnt = 0, L = 0, R = (int) relaxSegments.size() - 1;
        while (L <= R) {
          int m = (L + R) / 2;
          if (queries[iq].x <= relaxSegments[m].limit) {
            cnt = m + 1;
            L = m + 1;
          } else {
            R = m - 1;
          }
        }
        if (cnt >= 1) {
          small[iq] = tree.getmin(0, cnt - 1);
        }
      }
      for (int iq = 1; iq <= q; iq++) {
        print[iq] = max(print[iq], queries[iq].x - small[iq]);
        queries[iq].x *= -1;
      }
    }

    for (int iq = 1; iq <= q; iq++) {
      int maxDist = print[iq];
      if (maxDist > (int) 1e8) {
        maxDist = -1;
      }
      cout << maxDist << "\n";
    }
  }
  return 0;
}

Compilation message

new_home.cpp: In function 'int main()':
new_home.cpp:144:13: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  144 |     freopen ("input.txt", "r", stdin);
      |     ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7252 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7252 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 7252 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7252 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7252 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7252 KB Output isn't correct
2 Halted 0 ms 0 KB -