开始计概A下半学期。
This commit is contained in:
1 parent
0cfdc8499c
commit
38e97654e1
31 files changed
+2144
-110
No files matched your search
@@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
|
||||
constexpr std::size_t MAX_SIZE = 10001;
|
||||
|
||||
template <typename T>
|
||||
class Queue {
|
||||
T data[MAX_SIZE];
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-4
@@ -38,10 +38,7 @@ int main() {
|
||||
std::string target, pattern;
|
||||
std::cin >> target >> pattern;
|
||||
for (const auto i : find_substring_pos(target, pattern)) {
|
||||
std::cout << i + 1 << std::endl;
|
||||
}
|
||||
for (const auto val : prefix_function(pattern)) {
|
||||
std::cout << val << " ";
|
||||
std::cout << i << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
std::vector<int> get_next_vector(const std::string& s) {
|
||||
std::vector<int> next(s.size() + 1);
|
||||
next[0] = -1;
|
||||
for (int i = 0; i < next.size() - 1; i++) { // 实际上写入下一位
|
||||
int j = next[i];
|
||||
while (j != -1 && s[i] != s[j]) { // j = -1: 完全不匹配,s[i]==s[j]: 直接能用
|
||||
j = next[j];
|
||||
}
|
||||
if (j == -1 || s[i] == s[j]) { j++; }
|
||||
next[i + 1] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
std::vector<int> get_optimized_next_vector(const std::string& s, const std::vector<int>& next) {
|
||||
std::vector<int> next_optimized(next.size());
|
||||
next_optimized[0] = -1;
|
||||
next_optimized[next.size() - 1] = next[next.size() - 1];
|
||||
for (int i = 1; i < next.size() - 1; i++) {
|
||||
if (s[next[i]] == s[i]) {
|
||||
next_optimized[i] = next_optimized[next[i]];
|
||||
} else {
|
||||
next_optimized[i] = next[i];
|
||||
}
|
||||
}
|
||||
return next_optimized;
|
||||
}
|
||||
|
||||
std::vector<int> find_substring_pos(const std::string& target, const std::string& pattern) {
|
||||
std::vector<int> matched_pos;
|
||||
const std::vector<int> next_vector = get_optimized_next_vector(pattern, get_next_vector(pattern));
|
||||
int j = 0;
|
||||
for (int i = 0; i < target.size(); i++) {
|
||||
while (j > -1 && target[i] != pattern[j]) {
|
||||
j = next_vector[j];
|
||||
}
|
||||
if (j == -1) {
|
||||
j = 0; // 完全失配,直接 i++ j++
|
||||
continue;
|
||||
}
|
||||
if (target[i] == pattern[j]) { j++; }
|
||||
if (j == pattern.size()) {
|
||||
matched_pos.push_back(i - static_cast<int>(pattern.size()) + 1);
|
||||
j = next_vector[j];
|
||||
}
|
||||
}
|
||||
return matched_pos;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, std::vector<int> vec) {
|
||||
for (const auto& elem : vec) {
|
||||
os << elem << " ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
std::string target, pattern;
|
||||
std::cin >> target >> pattern;
|
||||
std::clog << get_next_vector(pattern) << std::endl;
|
||||
std::clog << get_optimized_next_vector(pattern, get_next_vector(pattern)) << std::endl;
|
||||
for (const auto i : find_substring_pos(target, pattern)) {
|
||||
std::cout << i << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
using Expression = std::string; // 没有数字
|
||||
|
||||
bool is_operator(const char c) {
|
||||
return c == '+' || c == '-' || c == '*' || c == '/'
|
||||
|| c == '(' || c == ')';
|
||||
}
|
||||
|
||||
int get_priority(char c) {
|
||||
assert(is_operator(c));
|
||||
if (c == '+' || c == '-') { return 1; }
|
||||
if (c == '*' || c == '/') { return 2; }
|
||||
throw std::invalid_argument("Invalid operator!");
|
||||
}
|
||||
|
||||
class ExpressionTree {
|
||||
public:
|
||||
struct Node {
|
||||
char value;
|
||||
int depth = -1;
|
||||
Node *father = nullptr, *left = nullptr, *right = nullptr;
|
||||
|
||||
explicit Node(char c) : value(c) {}
|
||||
|
||||
[[nodiscard]] bool is_operator() const {
|
||||
return ::is_operator(value);
|
||||
}
|
||||
|
||||
[[nodiscard]] int get_priority() const {
|
||||
return ::get_priority(value);
|
||||
}
|
||||
};
|
||||
|
||||
Node* root = nullptr;
|
||||
int depth = -1;
|
||||
|
||||
void init_depths() {
|
||||
dfs([this](Node* node, int dfs_depth) {
|
||||
node->depth = dfs_depth;
|
||||
depth = std::max(depth, dfs_depth);
|
||||
});
|
||||
depth++;
|
||||
}
|
||||
|
||||
void init_with_infix(const Expression& expression) {
|
||||
std::stack<Node*> ops;
|
||||
std::stack<Node*> nums;
|
||||
|
||||
for (char c : expression) {
|
||||
if (!is_operator(c)) {
|
||||
nums.push(new Node(c));
|
||||
continue;
|
||||
}
|
||||
if (c == '(') {
|
||||
ops.push(new Node(c));
|
||||
continue;
|
||||
}
|
||||
if (c == ')') {
|
||||
while (ops.top()->value != '(') {
|
||||
construct_one_op(ops, nums);
|
||||
}
|
||||
ops.pop();
|
||||
continue;
|
||||
}
|
||||
Node* node = new Node(c);
|
||||
while (!ops.empty() && ops.top()->value != '('
|
||||
&& node->get_priority() <= ops.top()->get_priority()) {
|
||||
construct_one_op(ops, nums);
|
||||
}
|
||||
ops.push(node);
|
||||
}
|
||||
while (!ops.empty()) {
|
||||
construct_one_op(ops, nums);
|
||||
}
|
||||
root = nums.top();
|
||||
init_depths();
|
||||
}
|
||||
|
||||
protected:
|
||||
static void construct_one_op(std::stack<Node*>& ops, std::stack<Node*>& nums) {
|
||||
auto op = ops.top();
|
||||
ops.pop();
|
||||
auto num_right = nums.top();
|
||||
nums.pop();
|
||||
auto num_left = nums.top();
|
||||
nums.pop();
|
||||
op->left = num_left;
|
||||
op->right = num_right;
|
||||
num_left->father = op;
|
||||
num_right->father = op;
|
||||
nums.push(op);
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] Expression get_postfix() const {
|
||||
Expression expression;
|
||||
// 此代码正确,但是本人想试试 dfs
|
||||
// std::stack<std::pair<Node*, short>> stack; // 0: 没干过活,1: 玩过左,2: 玩过右
|
||||
// stack.emplace(root, 0);
|
||||
// while (!stack.empty()) {
|
||||
// // std::clog << "Top: " << stack.top().first->value << ", flag=" << stack.top().second << std::endl;
|
||||
// if (stack.top().second == 0) {
|
||||
// stack.top().second++;
|
||||
// if (stack.top().first->left != nullptr) {
|
||||
// stack.emplace(stack.top().first->left, 0);
|
||||
// }
|
||||
// } else if (stack.top().second == 1) {
|
||||
// stack.top().second++;
|
||||
// if (stack.top().first->right != nullptr) {
|
||||
// stack.emplace(stack.top().first->right, 0);
|
||||
// }
|
||||
// } else {
|
||||
// expression += stack.top().first->value;
|
||||
// stack.pop();
|
||||
// }
|
||||
// }
|
||||
dfs([&expression](Node* node, int _) {
|
||||
expression.push_back(node->value);
|
||||
}, 2);
|
||||
return expression;
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::string> get_string_lines() {
|
||||
std::vector<std::string> lines(depth * 2);
|
||||
dfs_with_id([&lines](Node* node, unsigned long long node_id) {
|
||||
lines[node->depth * 2].resize(node_id, ' ');
|
||||
lines[node->depth * 2][node_id - 1] = node->value;
|
||||
if (node->left != nullptr) {
|
||||
lines[node->depth * 2 + 1].resize(node_id - 1, ' ');
|
||||
lines[node->depth * 2 + 1][node_id - 2] = '/';
|
||||
}
|
||||
if (node->right != nullptr) {
|
||||
lines[node->depth * 2 + 1].resize(node_id + 1, ' ');
|
||||
lines[node->depth * 2 + 1][node_id] = '\\';
|
||||
}
|
||||
}, 2);
|
||||
lines.pop_back();
|
||||
return lines;
|
||||
}
|
||||
|
||||
long long calculate(const std::unordered_map<char, int>& variable_map, Node* node = nullptr) {
|
||||
if (node == nullptr) { node = root; }
|
||||
if (node->left == nullptr) { return variable_map.at(node->value); }
|
||||
long long left = calculate(variable_map, node->left);
|
||||
long long right = calculate(variable_map, node->right);
|
||||
if (node->value == '+') { return left + right; }
|
||||
if (node->value == '-') { return left - right; }
|
||||
if (node->value == '*') { return left * right; }
|
||||
if (node->value == '/') { return left / right; }
|
||||
throw std::logic_error("");
|
||||
}
|
||||
|
||||
protected:
|
||||
void dfs(const std::function<void(Node*, int)>& func,
|
||||
int func_entry = 0,
|
||||
int dfs_depth = 0,
|
||||
Node* node = nullptr) const {
|
||||
if (dfs_depth == 0) { node = root; }
|
||||
if (func_entry == 0) { func(node, dfs_depth); }
|
||||
if (node->left != nullptr) { dfs(func, func_entry, dfs_depth + 1, node->left); }
|
||||
if (func_entry == 1) { func(node, dfs_depth); }
|
||||
if (node->right != nullptr) { dfs(func, func_entry, dfs_depth + 1, node->right); }
|
||||
if (func_entry == 2) { func(node, dfs_depth); }
|
||||
}
|
||||
|
||||
void dfs_with_id(const std::function<void(Node*, unsigned long long)>& func,
|
||||
int func_entry = 0,
|
||||
unsigned long long node_id = 0,
|
||||
Node* node = nullptr) const {
|
||||
if (node == nullptr) { node = root, node_id = 1 << (depth - 1); }
|
||||
// std::clog << node_id << std::endl;
|
||||
unsigned long long depth_bit = 1ull << (depth - node->depth - 1);
|
||||
unsigned long long flipped_depth_bit = ~0ull ^ depth_bit;
|
||||
if (func_entry == 0) { func(node, node_id); }
|
||||
if (node->left != nullptr) {
|
||||
dfs_with_id(func, func_entry, (node_id & flipped_depth_bit) | (depth_bit >> 1), node->left);
|
||||
}
|
||||
if (func_entry == 1) { func(node, node_id); }
|
||||
if (node->right != nullptr) {
|
||||
dfs_with_id(func, func_entry, node_id | (depth_bit >> 1), node->right);
|
||||
}
|
||||
if (func_entry == 2) { func(node, node_id); }
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, ExpressionTree expression_tree) {
|
||||
for (const auto& line : expression_tree.get_string_lines()) {
|
||||
os << line << std::endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
Expression infix_expression;
|
||||
std::cin >> infix_expression;
|
||||
|
||||
ExpressionTree expression_tree;
|
||||
expression_tree.init_with_infix(infix_expression);
|
||||
std::cout << expression_tree.get_postfix() << std::endl;
|
||||
std::cout << expression_tree;
|
||||
|
||||
int n;
|
||||
std::cin >> n;
|
||||
std::unordered_map<char, int> variable_map;
|
||||
for (int i = 0; i < n; i++) {
|
||||
char c;
|
||||
int x;
|
||||
std::cin >> c >> x;
|
||||
variable_map[c] = x;
|
||||
}
|
||||
std::cout << expression_tree.calculate(variable_map) << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
class BinaryTree {
|
||||
public:
|
||||
using NodeIdx = int;
|
||||
|
||||
struct Node {
|
||||
char value;
|
||||
NodeIdx left = -1, right = -1;
|
||||
};
|
||||
|
||||
enum class FuncEntry { Pre, In, Post };
|
||||
|
||||
NodeIdx root = -1;
|
||||
std::vector<Node> nodes;
|
||||
|
||||
void init_with_lines(const std::vector<std::string>& lines) {
|
||||
nodes.reserve(lines.size());
|
||||
std::vector<int> lines_dashes(lines.size());
|
||||
int idx = 0;
|
||||
root = init_with_lines(lines, 0, idx);
|
||||
}
|
||||
|
||||
std::string prefix_traverse() {
|
||||
std::string traverse;
|
||||
traverse.reserve(nodes.size());
|
||||
dfs([&traverse, this](NodeIdx node, int dfs_depth) {
|
||||
traverse += nodes[node].value;
|
||||
}, FuncEntry::Pre);
|
||||
return traverse;
|
||||
}
|
||||
|
||||
std::string infix_traverse() {
|
||||
std::string traverse;
|
||||
traverse.reserve(nodes.size());
|
||||
dfs([&traverse, this](NodeIdx node, int dfs_depth) {
|
||||
traverse += nodes[node].value;
|
||||
}, FuncEntry::In);
|
||||
return traverse;
|
||||
}
|
||||
|
||||
std::string postfix_traverse() {
|
||||
std::string traverse;
|
||||
traverse.reserve(nodes.size());
|
||||
dfs([&traverse, this](NodeIdx node, int dfs_depth) {
|
||||
traverse += nodes[node].value;
|
||||
}, FuncEntry::Post);
|
||||
return traverse;
|
||||
}
|
||||
|
||||
protected:
|
||||
NodeIdx init_with_lines(const std::vector<std::string>& lines,
|
||||
int depth, int& idx) {
|
||||
if (idx >= lines.size() || lines[idx].size() - 1 < depth) { return -1; }
|
||||
char value;
|
||||
if ((value = lines[idx][lines[idx].size() - 1]) == '*') {
|
||||
idx++;
|
||||
return -1;
|
||||
}
|
||||
const NodeIdx node_idx = nodes.size();
|
||||
nodes.push_back(Node{value});
|
||||
idx++;
|
||||
nodes[node_idx].left = init_with_lines(lines, depth + 1, idx);
|
||||
nodes[node_idx].right = init_with_lines(lines, depth + 1, idx);
|
||||
return node_idx;
|
||||
}
|
||||
|
||||
void dfs(const std::function<void(NodeIdx, int)>& func,
|
||||
FuncEntry func_entry = FuncEntry::Pre,
|
||||
int dfs_depth = 0,
|
||||
NodeIdx node = -1
|
||||
) {
|
||||
if (dfs_depth == 0) { node = root; }
|
||||
if (func_entry == FuncEntry::Pre) { func(node, dfs_depth); }
|
||||
if (nodes[node].left != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].left); }
|
||||
if (func_entry == FuncEntry::In) { func(node, dfs_depth); }
|
||||
if (nodes[node].right != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].right); }
|
||||
if (func_entry == FuncEntry::Post) { func(node, dfs_depth); }
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
int n;
|
||||
std::cin >> n;
|
||||
|
||||
while (n--) {
|
||||
std::vector<std::string> lines;
|
||||
std::string s;
|
||||
while (std::cin >> s && s != "0") {
|
||||
lines.push_back(s);
|
||||
}
|
||||
|
||||
BinaryTree binary_tree;
|
||||
binary_tree.init_with_lines(lines);
|
||||
|
||||
std::cout << binary_tree.prefix_traverse() << std::endl
|
||||
<< binary_tree.postfix_traverse() << std::endl
|
||||
<< binary_tree.infix_traverse() << std::endl << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
class HuffmanTree {
|
||||
public:
|
||||
struct Node {
|
||||
long long weight;
|
||||
std::optional<std::string> content;
|
||||
Node *left = nullptr, *right = nullptr;
|
||||
|
||||
bool operator<(const Node& other) const {
|
||||
return weight < other.weight;
|
||||
}
|
||||
};
|
||||
|
||||
enum class DfsEntries { Pre, In, Post };
|
||||
|
||||
Node* root = nullptr;
|
||||
|
||||
explicit HuffmanTree(const std::unordered_map<std::string, long long>& freq_map) {
|
||||
std::priority_queue<Node*, std::vector<Node*>,
|
||||
std::function<bool(Node*, Node*)>>
|
||||
nodes_heap([](Node* a, Node* b) { return a->weight > b->weight; });
|
||||
for (const auto& [key, freq] : freq_map) {
|
||||
nodes_heap.push(new Node{.weight = freq, .content = key});
|
||||
}
|
||||
while (nodes_heap.size() > 1) {
|
||||
Node* node1 = nodes_heap.top();
|
||||
nodes_heap.pop();
|
||||
Node* node2 = nodes_heap.top();
|
||||
nodes_heap.pop();
|
||||
Node* new_node = new Node{.weight = node1->weight + node2->weight, .left = node1, .right = node2};
|
||||
nodes_heap.push(new_node);
|
||||
}
|
||||
root = nodes_heap.top();
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<bool>> get_encodings() {
|
||||
std::unordered_map<std::string, std::vector<bool>> encodings;
|
||||
if (root->left == nullptr && root->right == nullptr) {
|
||||
encodings[root->content.value()] = {false};
|
||||
} else {
|
||||
dfs_with_path([&encodings](Node* node, std::vector<bool> path) {
|
||||
if (!node->content.has_value()) { return; }
|
||||
encodings[node->content.value()] = std::move(path);
|
||||
});
|
||||
}
|
||||
return encodings;
|
||||
}
|
||||
|
||||
protected:
|
||||
void dfs_with_path(const std::function<void(Node*, std::vector<bool>)>& func,
|
||||
DfsEntries func_entry = DfsEntries::Pre) {
|
||||
std::vector<bool> path;
|
||||
dfs_with_path(func, func_entry, path);
|
||||
}
|
||||
|
||||
void dfs_with_path(const std::function<void(Node*, std::vector<bool>)>& func,
|
||||
DfsEntries func_entry,
|
||||
std::vector<bool>& path,
|
||||
Node* node = nullptr) {
|
||||
if (node == nullptr) { node = root; }
|
||||
if (func_entry == DfsEntries::Pre) { func(node, path); }
|
||||
if (node->left != nullptr) {
|
||||
path.push_back(false);
|
||||
dfs_with_path(func, func_entry, path, node->left);
|
||||
path.pop_back();
|
||||
}
|
||||
if (func_entry == DfsEntries::In) { func(node, path); }
|
||||
if (node->right != nullptr) {
|
||||
path.push_back(true);
|
||||
dfs_with_path(func, func_entry, path, node->right);
|
||||
path.pop_back();
|
||||
}
|
||||
if (func_entry == DfsEntries::Post) { func(node, path); }
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const std::vector<bool>& bintree_path) {
|
||||
for (const auto bin : bintree_path) {
|
||||
os << (bin ? 1 : 0);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
int n;
|
||||
std::cin >> n;
|
||||
|
||||
std::vector<std::string> keys(n);
|
||||
std::unordered_map<std::string, long long> freq_map;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int freq;
|
||||
std::cin >> keys[i] >> freq;
|
||||
freq_map[keys[i]] = freq;
|
||||
}
|
||||
|
||||
HuffmanTree huffman_tree(freq_map);
|
||||
auto encodings = huffman_tree.get_encodings();
|
||||
for (const auto& key : keys) {
|
||||
std::cout << key << ' ' << encodings[key] << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 带权并查集。权重记录该节点到父节点的边的边权(保证一切根节点权重为 0)
|
||||
*/
|
||||
class DsuWeighted {
|
||||
public:
|
||||
using NodeIdx = int;
|
||||
|
||||
struct Node {
|
||||
NodeIdx parent = -1;
|
||||
int weight = 0;
|
||||
std::size_t size = 1;
|
||||
};
|
||||
|
||||
std::vector<Node> nodes;
|
||||
const int groups_amount;
|
||||
|
||||
explicit DsuWeighted(const std::size_t n, int groups = 2) : nodes(n), groups_amount(groups) {
|
||||
for (auto i = 0; i < n; i++) {
|
||||
nodes[i].parent = i;
|
||||
}
|
||||
}
|
||||
|
||||
NodeIdx find(const NodeIdx x) {
|
||||
if (nodes[x].parent == x) { return x; }
|
||||
find(nodes[x].parent);
|
||||
nodes[x].weight += nodes[nodes[x].parent].weight;
|
||||
nodes[x].weight %= groups_amount;
|
||||
return nodes[x].parent = find(nodes[x].parent);
|
||||
}
|
||||
|
||||
int get_weight(const NodeIdx x) {
|
||||
find(x);
|
||||
return nodes[x].weight;
|
||||
}
|
||||
|
||||
void unite(NodeIdx x, NodeIdx y, int weight_delta = 0) {
|
||||
auto x_root = find(x), y_root = find(y);
|
||||
if (x_root == y_root) { return; }
|
||||
if (nodes[x_root].size > nodes[y_root].size) {
|
||||
std::swap(x, y);
|
||||
std::swap(x_root, y_root);
|
||||
weight_delta = -weight_delta;
|
||||
}
|
||||
nodes[x_root].weight += weight_delta + nodes[y].weight - nodes[x].weight;
|
||||
nodes[x_root].weight %= groups_amount;
|
||||
nodes[x_root].parent = y_root;
|
||||
nodes[y_root].size += nodes[x_root].size;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
std::cout.tie(nullptr);
|
||||
|
||||
int test_cases_amount;
|
||||
std::cin >> test_cases_amount;
|
||||
while (test_cases_amount--) {
|
||||
int cases_amount, queries_amount;
|
||||
std::cin >> cases_amount >> queries_amount;
|
||||
|
||||
DsuWeighted dsu(cases_amount, 2);
|
||||
while (queries_amount--) {
|
||||
char op;
|
||||
int case_id_1, case_id_2;
|
||||
std::cin >> op >> case_id_1 >> case_id_2;
|
||||
case_id_1--, case_id_2--;
|
||||
if (op == 'D') {
|
||||
dsu.unite(case_id_1, case_id_2, 1);
|
||||
} else if (op == 'A') {
|
||||
if (dsu.find(case_id_1) != dsu.find(case_id_2)) {
|
||||
std::cout << "Not sure yet." << std::endl;
|
||||
} else {
|
||||
if ((dsu.get_weight(case_id_1) - dsu.get_weight(case_id_2)) % 2 == 0) {
|
||||
std::cout << "In the same gang." << std::endl;
|
||||
} else {
|
||||
std::cout << "In different gangs." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using NodeIdx = std::size_t;
|
||||
static constexpr NodeIdx NULL_IDX = static_cast<NodeIdx>(-1);
|
||||
|
||||
template <typename T>
|
||||
class Tree {
|
||||
public:
|
||||
enum class FuncEntry { Pre, Post };
|
||||
|
||||
struct Node {
|
||||
T value;
|
||||
NodeIdx parent = NULL_IDX;
|
||||
std::vector<NodeIdx> children;
|
||||
};
|
||||
|
||||
std::vector<Node> nodes;
|
||||
NodeIdx root = NULL_IDX;
|
||||
|
||||
NodeIdx add_node(const Node& node_obj) {
|
||||
nodes.push_back(node_obj);
|
||||
return nodes.size() - 1;
|
||||
}
|
||||
|
||||
void init_with_dfs(const std::string& dfs_string) {
|
||||
root = add_node({.value = T()});
|
||||
init_with_dfs(dfs_string, 0, root);
|
||||
}
|
||||
|
||||
int get_height() {
|
||||
int depth = -1;
|
||||
dfs([&depth](NodeIdx node, int dfs_depth) { depth = std::max(depth, dfs_depth); });
|
||||
return depth;
|
||||
}
|
||||
|
||||
protected:
|
||||
void init_with_dfs(const std::string& dfs_string, std::size_t s_idx, NodeIdx node) {
|
||||
if (s_idx >= dfs_string.size()) { return; }
|
||||
if (dfs_string[s_idx] == 'd') {
|
||||
auto new_node = add_node({.value = T(), .parent = node});
|
||||
nodes[node].children.push_back(new_node);
|
||||
init_with_dfs(dfs_string, s_idx + 1, nodes[node].children.back());
|
||||
} else {
|
||||
init_with_dfs(dfs_string, s_idx + 1, nodes[node].parent);
|
||||
}
|
||||
}
|
||||
|
||||
void dfs(const std::function<void(NodeIdx, int)>& func,
|
||||
FuncEntry func_entry = FuncEntry::Post,
|
||||
int depth = 0,
|
||||
NodeIdx node = NULL_IDX
|
||||
) {
|
||||
if (depth == 0) { node = root; }
|
||||
if (func_entry == FuncEntry::Pre) { func(node, depth); }
|
||||
for (auto child : nodes[node].children) {
|
||||
dfs(func, func_entry, depth + 1, child);
|
||||
}
|
||||
if (func_entry == FuncEntry::Post) { func(node, depth); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class BinaryTree {
|
||||
public:
|
||||
enum class FuncEntry { Pre, In, Post };
|
||||
|
||||
struct Node {
|
||||
T value;
|
||||
NodeIdx parent = NULL_IDX, left = NULL_IDX, right = NULL_IDX;
|
||||
};
|
||||
|
||||
std::vector<Node> nodes;
|
||||
NodeIdx root = -1;
|
||||
|
||||
NodeIdx add_node(Node node_obj) {
|
||||
nodes.push_back(node_obj);
|
||||
return nodes.size() - 1;
|
||||
}
|
||||
|
||||
void init_from_tree(const Tree<T>& tree) {
|
||||
root = add_node({});
|
||||
init_from_tree(tree, tree.root, 0);
|
||||
}
|
||||
|
||||
int get_height() {
|
||||
int depth = -1;
|
||||
dfs([&depth](NodeIdx node, int dfs_depth) { depth = std::max(depth, dfs_depth); });
|
||||
return depth;
|
||||
}
|
||||
|
||||
protected:
|
||||
void init_from_tree(const Tree<T>& tree, NodeIdx binary_tree_node, NodeIdx tree_node) {
|
||||
bool first_child = false;
|
||||
NodeIdx current_parent = NULL_IDX;
|
||||
for (auto child : tree.nodes[tree_node].children) {
|
||||
if (!first_child) {
|
||||
first_child = true;
|
||||
NodeIdx new_node = add_node({.value = T(), .parent = binary_tree_node});
|
||||
nodes[binary_tree_node].left = new_node;
|
||||
current_parent = nodes[binary_tree_node].left;
|
||||
init_from_tree(tree, nodes[binary_tree_node].left, child);
|
||||
continue;
|
||||
}
|
||||
NodeIdx new_node = add_node({.value = T(), .parent = current_parent});
|
||||
nodes[current_parent].right = new_node;
|
||||
current_parent = nodes[current_parent].right;
|
||||
init_from_tree(tree, current_parent, child);
|
||||
}
|
||||
}
|
||||
|
||||
void dfs(const std::function<void(NodeIdx, int)>& func,
|
||||
FuncEntry func_entry = FuncEntry::Pre,
|
||||
int dfs_depth = 0,
|
||||
NodeIdx node = -1
|
||||
) {
|
||||
if (dfs_depth == 0) { node = root; }
|
||||
if (func_entry == FuncEntry::Pre) { func(node, dfs_depth); }
|
||||
if (nodes[node].left != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].left); }
|
||||
if (func_entry == FuncEntry::In) { func(node, dfs_depth); }
|
||||
if (nodes[node].right != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].right); }
|
||||
if (func_entry == FuncEntry::Post) { func(node, dfs_depth); }
|
||||
}
|
||||
};
|
||||
|
||||
struct ManualVoid {};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
std::cout.tie(nullptr);
|
||||
|
||||
std::string dfs_string;
|
||||
for (int i = 0; std::cin >> dfs_string && dfs_string != "#"; i++) {
|
||||
Tree<ManualVoid> tree;
|
||||
tree.init_with_dfs(dfs_string);
|
||||
BinaryTree<ManualVoid> binary_tree;
|
||||
binary_tree.init_from_tree(tree);
|
||||
std::cout << "Tree " << i + 1 << ": " << tree.get_height() << " => " << binary_tree.get_height() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class Graph {
|
||||
public:
|
||||
struct EdgeNode {
|
||||
std::size_t end_vertex;
|
||||
int weight = 1;
|
||||
std::unique_ptr<EdgeNode> next = nullptr;
|
||||
|
||||
EdgeNode(std::size_t end_vertex, int weight, std::unique_ptr<EdgeNode>&& next = nullptr) {
|
||||
this->end_vertex = end_vertex;
|
||||
this->weight = weight;
|
||||
this->next = std::move(next);
|
||||
}
|
||||
};
|
||||
|
||||
struct VertexNode {
|
||||
int value = -1;
|
||||
std::unique_ptr<EdgeNode> first_edge = nullptr;
|
||||
};
|
||||
|
||||
std::vector<VertexNode> vertices;
|
||||
|
||||
explicit Graph(int vertices_size) : vertices(vertices_size) {}
|
||||
|
||||
void add_edge(std::size_t start_vertex, std::size_t end_vertex, int weight = 1, const bool two_dirs = false) {
|
||||
// 效率上考量,向头部加边
|
||||
// if (vertices[start_vertex].first_edge == nullptr) {
|
||||
// vertices[start_vertex].first_edge = std::make_unique<EdgeNode>(end_vertex, weight);
|
||||
// } else {
|
||||
// auto head = std::move(vertices[start_vertex].first_edge);
|
||||
// vertices[start_vertex].first_edge = std::make_unique<EdgeNode>(end_vertex, weight);
|
||||
// vertices[start_vertex].first_edge->next = std::move(head);
|
||||
// }
|
||||
vertices[start_vertex].first_edge = std::make_unique<EdgeNode>(
|
||||
end_vertex, weight, std::move(vertices[start_vertex].first_edge));
|
||||
if (two_dirs) {
|
||||
add_edge(end_vertex, start_vertex, weight, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
int n;
|
||||
std::cin >> n;
|
||||
Graph graph(n);
|
||||
for (int i = 0; i < n - 1; i++) {
|
||||
char node_c;
|
||||
int edges_amount;
|
||||
std::cin >> node_c >> edges_amount;
|
||||
for (int _ = 0; _ < edges_amount; _++) {
|
||||
int edge_weight;
|
||||
std::cin >> node_c >> edge_weight;
|
||||
graph.add_edge(i, node_c - 'A', edge_weight, true);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user