QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#450959 | #8793. Toilets | ucup-team173 | WA | 388ms | 58636kb | C++20 | 8.1kb | 2024-06-22 19:56:36 | 2024-06-22 19:56:36 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
constexpr bool debug = false;
#else
constexpr bool debug = true;
#endif
using i64 = long long;
struct event {
i64 time, pos, dur;
int type, dir, id;
/*
case available
type = 0: toilet emerge pos
type = 1: person emerge pos, dur, dir, id
type = 2: person finds toilet pos, id
*/
bool operator < (const event &e) const {
if(time != e.time) return time < e.time;
if(type != e.type) return type < e.type;
if(type) return id < e.id;
else return pos < e.pos;
}
bool operator == (const event &e) const {
return time == e.time && type == e.type && pos == e.pos && dur == e.dur && dir == e.dir && id == e.id;
}
};
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
i64 n, m, L;
cin >> n >> m >> L;
set<i64> toilet;
map<i64, set<int>> person_dir[2]; // 1: pos 0: neg
map<i64, array<int, 2>> toilet_near;
for(int i = 0; i < m; i++) {
i64 x;
cin >> x;
toilet.insert(x);
toilet_near[x] = {0, 0};
}
set<event> q;
vector<array<i64, 4>> person(n + 1); // <time, pos, dir, dur>
vector<event> person_near(n + 1);
for(int i = 1; i <= n; i++) {
int t, p, d;
string s;
cin >> t >> p >> s >> d;
person_near[i].pos = -1;
if(s == "+") {
q.insert({t, p, d, 1, 1, i});
person[i] = {t, p, 1, d};
} else {
q.insert({t, p, d, 1, 0, i});
person[i] = {t, p, 0, d};
}
}
auto norm = [&](i64 x) { return (x % L + L) % L; };
auto dist = [&](int id, i64 pos, i64 ti) -> i64 { // time to go _pos_ for person _id_ at time _ti_
if(pos == -1) return 1e18;
ti -= person[id][0];
return person[id][2] == 1 ? norm(pos - ti - person[id][1]) : norm(person[id][1] - ti - pos);
};
auto find_right = [&](set<i64> &st, i64 x) -> i64 {
if(st.empty()) return -1;
auto it = st.lower_bound(x);
if(it == st.end()) return *st.begin();
return *it;
};
auto find_left = [&](set<i64> &st, i64 x) -> i64 {
if(st.empty()) return -1;
auto it = st.upper_bound(x);
if(it == st.begin()) return *st.rbegin();
return *prev(it);
};
auto find_right_id = [&](map<i64, set<int>> &st, i64 x) -> int {
if(st.empty()) return -1;
auto it = st.lower_bound(x);
if(it == st.end()) return *st.begin()->second.begin();
return *it->second.begin();
};
auto find_left_id = [&](map<i64, set<int>> &st, i64 x) -> int {
if(st.empty()) return -1;
auto it = st.upper_bound(x);
if(it == st.begin()) return *st.rbegin()->second.begin();
return *prev(it)->second.begin();
};
i64 cnt = 0;
vector<pair<i64, i64>> ans(n + 1);
auto link_person = [&](i64 ti, i64 pos, i64 dur, i64 ty, int dir, int id) { // try to link person _id_ to toilet and maintain the queue
i64 near = dir == 1 ? find_right(toilet, norm(pos + ti - person[id][0])) : find_left(toilet, norm(pos - ti + person[id][0]));
if(debug) cerr << " near = " << near << '\n';
if(near == -1) return;
int o = toilet_near[near][!dir];
if(o == 0) {
toilet_near[near][!dir] = id;
person_near[id] = {ti + dist(id, near, ti), near, dur, 2, dir, id};
q.insert(person_near[id]);
} else {
if(debug) cerr << " dist1 = " << dist(id, near, ti) << ' ' << "dist2 = " << dist(o, near, ti) << '\n';
if(make_pair(dist(id, near, ti), id) < make_pair(dist(o, near, ti), o)) {
q.erase(person_near[o]); // should I modify person_near[o] ?
person_near[o] = {0, -1, 0, 0, 0, 0};
toilet_near[near][!dir] = id;
person_near[id] = {ti + dist(id, near, ti), near, dur, 2, dir, id};
q.insert(person_near[id]);
}
}
};
while(cnt < n) {
if(debug) cerr << "-----------------------------------\n";
auto [ti, pos, dur, ty, dir, id] = *q.begin();
q.erase(q.begin());
if(ty == 0) { // toilet emerge
toilet.insert(pos);
int left = find_left_id(person_dir[1], norm(pos - ti));
int right = find_right_id(person_dir[0], norm(pos + ti));
if(debug) cerr << " dist1 = " << dist(left, pos, ti) << ' ' << "dist2 = " << dist(left, person_near[left].pos, ti) << '\n';
if(left != -1 && dist(left, pos, ti) < dist(left, person_near[left].pos, ti)) {
q.erase(person_near[left]);
toilet_near[person_near[left].pos][0] = 0;
toilet_near[pos][0] = left;
person_near[left] = {ti + dist(left, pos, ti), pos, 0, 2, 0, left};
q.insert(person_near[left]);
}
if(right != -1 && dist(right, pos, ti) < dist(right, person_near[right].pos, ti)) {
q.erase(person_near[right]);
toilet_near[person_near[right].pos][1] = 0;
toilet_near[pos][1] = right;
person_near[right] = {ti + dist(right, pos, ti), pos, 0, 2, 0, right};
q.insert(person_near[right]);
}
} else if(ty == 1) { // person emerge
person_dir[dir][norm(dir == 1 ? pos - ti : pos + ti)].insert(id);
link_person(ti, pos, dur, ty, dir, id);
} else { // person finds toilet
dur = person[id][3], dir = person[id][2];
ans[id] = {pos, ti}, cnt++;
i64 pp = norm(dir == 1 ? pos - ti : pos + ti);
person_dir[dir][pp].erase(id);
if(person_dir[dir][pp].empty()) person_dir[dir].erase(pp);
int o1 = toilet_near[pos][dir];
pp = norm(dir == 1 ? person[id][1] - person[id][0] : person[id][1] + person[id][0]);
int o2 = dir == 1 ? find_left_id(person_dir[1], pp) : find_right_id(person_dir[0], pp);
toilet_near[pos] = {0, 0};
toilet.erase(pos);
q.insert({ti + dur, pos, 0, 0, 0, 0});
if(o1) { // no need to check o != id
q.erase(person_near[o1]);
person_near[o1] = {0, -1, 0, 0, 0, 0};
link_person(ti, person[o1][1], person[o1][3], 1, person[o1][2], o1);
}
if(o2 != -1) {
link_person(ti, person[o2][1], person[o2][3], 1, person[o2][2], o2);
}
}
if(!debug) continue;
cerr << "ti = " << ti << ' ' << "pos = " << pos << ' ' << "dur = " << dur << ' ' << "ty = " << ty << ' ' << "dir = " << dir << ' ' << "id = " << id << '\n';
cerr << "toilet: ";
for(auto x : toilet) cerr << x << ' ';
cerr << '\n';
cerr << "person_dir[0]: ";
for(auto [x, y] : person_dir[0]) {
cerr << x << "(";
for(auto z : y) cerr << z << (z == *y.rbegin() ? "" : ",");
cerr << ") ";
}
cerr << '\n';
cerr << "person_dir[1]: ";
for(auto [x, y] : person_dir[1]) {
cerr << x << "(";
for(auto z : y) cerr << z << (z == *y.rbegin() ? "" : ",");
cerr << ") ";
}
cerr << '\n';
cerr << "events:\n";
cerr << "tim pos dur typ dir id\n";
for(auto x : q) {
cerr << setw(3) << x.time << ' ' << setw(3) << x.pos << ' '
<< setw(3) << x.dur << ' ' << setw(3) << x.type << ' '
<< setw(3) << x.dir << ' ' << setw(3) << x.id << '\n';
}
}
for(int i = 1; i <= n; i++) {
cout << ans[i].first << ' ' << ans[i].second << '\n';
}
/*
i64 time, pos, dur;
int type, dir, id;
case available
type = 0: toilet emerge pos
type = 1: person emerge pos, dur, dir, id
type = 2: person finds toilet pos, id
*/
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3820kb
input:
5 3 45 10 20 30 0 0 + 200 2 5 + 10 20 40 - 100 21 16 + 10 50 0 + 22
output:
20 20 10 7 30 30 10 60 10 105
result:
ok 10 numbers
Test #2:
score: 0
Accepted
time: 0ms
memory: 3524kb
input:
1 1 1 0 0 0 - 1
output:
0 0
result:
ok 2 number(s): "0 0"
Test #3:
score: 0
Accepted
time: 0ms
memory: 3564kb
input:
5 3 33 3 24 23 12 24 - 9 16 28 - 1 17 27 - 9 19 26 - 5 32 22 - 2
output:
24 12 23 21 3 41 24 21 3 51
result:
ok 10 numbers
Test #4:
score: 0
Accepted
time: 0ms
memory: 3860kb
input:
4 5 6 1 3 4 2 0 2 1 + 2 7 3 + 6 9 0 + 9 10 1 - 6
output:
1 2 3 7 0 9 1 10
result:
ok 8 numbers
Test #5:
score: 0
Accepted
time: 1ms
memory: 3760kb
input:
736 30 100500 99382 85511 67593 53450 55531 9959 37170 57546 52666 62342 50707 71285 65933 19874 2092 100255 23965 83091 45652 64171 100128 19518 21445 96069 79781 52642 37943 95321 97569 69154 0 44619 + 7052 2 72499 + 29247 3 53785 - 35614 5 81887 + 64475 7 8561 + 31641 8 95471 - 22654 9 61040 - 44...
output:
53450 310331 95321 22824 53450 338 67593 186711 23965 718911 95321 158 83091 580958 62342 71243 50707 602820 83091 183 2092 375130 96069 552638 100128 541370 64171 5285 50707 288492 45652 795873 2092 284 85511 720931 55531 713428 53450 483192 69154 5302 83091 155808 57546 351069 2092 231938 85511 60...
result:
ok 1472 numbers
Test #6:
score: -100
Wrong Answer
time: 388ms
memory: 58636kb
input:
200000 200000 200000 45589 41206 151226 67898 73967 140984 73325 186330 35522 72131 147731 139390 123121 817 198939 98824 55631 84079 28987 108012 22006 143408 11442 195253 179662 189693 142207 99819 103750 166626 140235 140358 148893 170212 14967 98607 193895 19535 87565 166568 179135 11569 109260 ...
output:
99245 0 99244 1 99243 2 99242 3 99241 4 99240 5 99239 6 99238 7 99237 8 99236 9 99235 10 99234 11 99233 12 99232 13 99231 14 99230 15 99229 16 99228 17 99227 18 99226 19 99225 20 99224 21 99223 22 99222 23 99221 24 99220 25 99219 26 99218 27 99217 28 99216 29 99215 30 99214 31 99213 32 99212 33 9921...
result:
wrong answer 3rd numbers differ - expected: '159669', found: '99244'