This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// median?
#include <bits/stdc++.h>
using namespace std;
const long long int INF = 1e18;
long long int K, N;
long long int build1, build2;
char zone1, zone2;
long long int Dmin = 0;
struct Place {
char zone;
long long int building;
};
vector<pair<Place, Place> > people;
vector<long long int> person;
vector<long long int> pref;
bool cmp(pair<Place, Place> &a, pair<Place, Place> &b) {
return (a.first.building + a.second.building) < (b.first.building + b.second.building);
}
long long int cost(long long int currK) {
long long int currMin = 0;
for (int j = 0; j < people.size(); j++) {
currMin += abs(people[j].first.building - currK);
currMin++;
currMin += abs(people[j].second.building - currK);
}
return currMin;
}
class MedianFinder {
private:
set<int, greater<int>> leftSet;
set<int> rightSet;
public:
long long int leftSum;
long long int rightSum;
MedianFinder() {
leftSum = 0;
rightSum = 0;
}
void insert(int x) {
int median = (leftSet.size() ? *leftSet.begin() : 1000000001);
if (x <= median) {
leftSet.insert(x);
leftSum += x;
} else {
rightSet.insert(x);
rightSum += x;
}
if (rightSet.size() + 1 < leftSet.size()) { // there's too little elements
int nxt = *leftSet.begin();
rightSet.insert(nxt);
leftSet.erase(leftSet.begin());
leftSum -= nxt;
rightSum += nxt;
} else if (leftSet.size() < rightSet.size()) {
int nxt = *rightSet.begin();
leftSet.insert(nxt);
rightSet.erase(rightSet.begin());
leftSum += nxt;
rightSum -= nxt;
}
}
void print() {
cout << "Left: ";
for (auto l: leftSet) {
cout << l << ", ";
}
cout << "\n";
cout << "Right: ";
for (auto l: rightSet) {
cout << l << ", ";
}
cout << "\n";
}
};
int main() {
cin >> K >> N;
for (int i = 0; i < N; i++) {
cin >> zone1 >> build1 >> zone2 >> build2;
if (zone1 == zone2) {
Dmin += abs(build2 - build1);
} else {
people.push_back(make_pair(
(Place){zone1, build1},
(Place){zone2, build2}
));
person.push_back(build1);
person.push_back(build2);
}
}
int M = person.size();
long long int possibleMin = INF;
if (M == 0) possibleMin = 0;
else if (K == 1) {
sort(person.begin(), person.end());
for (int i = M/2; i <= M/2 + 1; i++) {
possibleMin = min(possibleMin, cost(person[i]));
}
cout << possibleMin + Dmin << "\n";
} else {
sort(people.begin(), people.end(), cmp);
int actualPeople = people.size();
Dmin += actualPeople; // each person needs to cross the bridge
MedianFinder mf = MedianFinder();
pref.resize(actualPeople + 1);
for (int i = 1; i < actualPeople + 1; i++) {
mf.insert(people[i-1].first.building);
mf.insert(people[i-1].second.building);
pref[i] = mf.rightSum - mf.leftSum;
}
MedianFinder mf1 = MedianFinder();
long long int ans = pref[actualPeople];
for (int i = actualPeople; i; i--) {
mf1.insert(people[i-1].first.building);
mf1.insert(people[i-1].second.building);
ans = min(ans, mf1.rightSum - mf1.leftSum + pref[i - 1]);
}
cout << Dmin + ans << "\n";
}
}
Compilation message (stderr)
bridge.cpp: In function 'long long int cost(long long int)':
bridge.cpp:29:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<Place, Place> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
29 | for (int j = 0; j < people.size(); j++) {
| ~~^~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |