Files
contests/2022/republic/12/arbore/arbore.cpp
2022-06-01 20:14:50 +03:00

132 lines
3.9 KiB
C++

#include <iostream>
#include <list>
using namespace std;
struct Node {
Node *left;
Node *right;
int64_t height;
};
void createNewNode(Node &parent, list<Node> &freeNodesLeft, list<Node> &freeNodesRight, int64_t new_height, bool direction) {
// Found a node that will not increase total height. Using
Node newNode;
newNode.height = new_height;
freeNodesLeft.push_back(newNode);
freeNodesRight.push_back(newNode);
if(!direction) {
parent.left = &newNode;
} else {
parent.right = &newNode;
}
}
int64_t calculateHeight(int64_t N, int64_t leftHeight, int64_t rightHeight) {
if (N == 1) {
return 0;
}
int64_t totalHeight = 0;
Node parentNode;
parentNode.height = 0;
list<Node> freeNodesLeft;
list<Node> freeNodesRight;
freeNodesLeft.push_back(parentNode);
freeNodesRight.push_back(parentNode);
int64_t longestRoad = max(leftHeight, rightHeight);
// Calculate all houses after first one
for (int64_t i = 1; i < N; i++) {
Node lowestNodeLeft;
lowestNodeLeft.height = longestRoad * N;
auto lowestNodeLeftIt = freeNodesLeft.end();
bool foundFreeSolution = false;
// Find lowest left node. Also check if using any of the existing nodes will not increase total height
for (auto it = freeNodesLeft.begin(); it != freeNodesLeft.end(); it++) {
Node node = *it;
int64_t new_height = node.height + leftHeight;
if (new_height <= totalHeight) {
// Found a node that will not increase total height. Using it
createNewNode(node, freeNodesLeft, freeNodesRight, new_height, 0);
freeNodesLeft.erase(it);
foundFreeSolution = true;
break;
}
if (new_height < lowestNodeLeft.height) {
lowestNodeLeft = node;
lowestNodeLeftIt = it;
}
}
if (foundFreeSolution) {
continue;
}
Node lowestNodeRight;
lowestNodeRight.height = longestRoad * N;
auto lowestNodeRightIt = freeNodesRight.end();
// Find lowest right node. Also check if using any of the existing nodes will not increase total height
for (auto it = freeNodesRight.begin(); it != freeNodesRight.end(); it++) {
Node node = *it;
int64_t new_height = node.height + rightHeight;
if (new_height <= totalHeight) {
// Found a node that will not increase total height. Using
createNewNode(node, freeNodesLeft, freeNodesRight, new_height, 1);
freeNodesRight.erase(it);
foundFreeSolution = true;
break;
}
if (new_height < lowestNodeRight.height) {
lowestNodeRight = node;
lowestNodeRightIt = it;
}
}
if (foundFreeSolution) {
continue;
}
int64_t newHeightLeft = lowestNodeLeft.height + leftHeight;
int64_t newHeightRight = lowestNodeRight.height + rightHeight;
if (newHeightLeft < newHeightRight) {
createNewNode(lowestNodeLeft, freeNodesLeft, freeNodesRight, newHeightLeft, 0);
freeNodesLeft.erase(lowestNodeLeftIt);
totalHeight = newHeightLeft;
} else {
createNewNode(lowestNodeRight, freeNodesLeft, freeNodesRight, newHeightRight, 1);
freeNodesRight.erase(lowestNodeRightIt);
totalHeight = newHeightRight;
}
//cout << "i=" << i << "; total_height=" << totalHeight << endl;
}
return totalHeight;
}
int main() {
int64_t T;
cin >> T;
int64_t N, A, B;
for (int i = 0; i < T; i++) {
cin >> N >> A >> B;
cout << calculateHeight(N, A, B) << endl;
}
return 0;
}