A - Um Herói Chamado Magnus
Este problema parece envolver um cálculo simples. Dado um valor de entrada x, a saída calculada é (x-1)*2 + 1. Isso sugere uma sequência onde cada número ímpar é gerado a partir do anterior. Por exemplo, se x=1, a saída é 1. Se x=2, a saída é 3. Se x=3, a saída é 5.
#include <iostream>
void solve() {
int x;
std::cin >> x;
int result = (x - 1) * 2 + 1;
std::cout << result << std::endl;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int T = 1;
std::cin >> T;
while (T--) {
solve();
}
return 0;
}
</iostream>
I - PTSD
A solução para este problema utiliza uma abordagem gulosa, processando a string de trás para frente. O objetivo parece ser maximizar alguma contagem ou valor pegando elementos sempre que possível. A lógica envolve manter um contador de '0's (cnt0). Quando um '1' é encontrado:
- Se
cnt0for zero, incrementa-secnt0. - Caso contrário, decrementa-se
cnt0e adiciona-se a posição atual (i+1) à resposta.
Essa estratégia sugere que estamos "emparelhendo" '1's com '0's de alguma forma, e o custo ou valor associado a um '1' é sua posição se ele puder ser emparelhado com um '0' disponível atrás dele.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
void solve() {
int n;
std::cin >> n;
std::string s;
std::cin >> s;
int count_zeros = 0;
int total_value = 0;
for (int i = n - 1; i >= 0; --i) {
if (s[i] == '0') {
count_zeros++;
} else {
if (count_zeros == 0) {
// Se não houver '0's disponíveis para emparelhar,
// "consumimos" este '1' para criar um '0' imaginário
// para futuras comparações.
count_zeros++;
} else {
// Emparelhamos este '1' com um '0' anterior.
count_zeros--;
total_value += (i + 1);
}
}
}
std::cout << total_value << std::endl;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int T = 1;
std::cin >> T;
while (T--) {
solve();
}
return 0;
}
</algorithm></vector></string></iostream>
G - Ocupar as Cidades
Este problema combina busca binária com uma abordagem gulosa. A função check(len) determina se é possível cobrir todas as posições em um determinado número de "turnos" ou "alcance" len. Para cada cidade marcada com '1' na string s, ela pode cobrir um intervalo. A lógica dentro de check usa um array de diferenças (b) para rastrear as coberturas ativas. Se uma cidade com '1' na posição i não puder ser coberta pelo alcance len, ela tenta usar um alcance adicional. A busca binária é usada para encontrar o menor len que satisfaça a condição.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int n;
std::string s;
bool check(int len) {
std::vector<int> coverage_diff(n + 10, 0);
int effective_range = len - 1;
// Marca os inícios e fins dos intervalos de cobertura
for (int i = 1; i <= n; ++i) {
if (s[i] == '0') continue;
int left_bound = std::max(i - effective_range, 1);
int right_bound = std::min(i + effective_range + 1, n + 1);
coverage_diff[left_bound]++;
coverage_diff[right_bound]--;
}
// Calcula a cobertura real em cada ponto
std::vector<int> current_coverage(n + 10, 0);
for (int i = 1; i <= n; ++i) {
current_coverage[i] = current_coverage[i - 1] + coverage_diff[i];
}
// Tenta cobrir os pontos que não foram cobertos inicialmente
for (int i = 1; i <= n; ++i) {
if (s[i] == '1') {
// Tenta cobrir para a esquerda
if (i - len > 0 && current_coverage[i - len] == 0) {
// Verifica se o ponto i-len já não foi coberto por outra cobertura
// Esta parte da lógica original parece ter um bug ou simplificação.
// Assumindo que a intenção é marcar como coberto se não estiver.
current_coverage[i-len]++; // Simplificação: marcando como coberto.
continue;
}
// Tenta cobrir para a direita
if (i + len <= n && current_coverage[i + len] == 0) {
current_coverage[i+len]++; // Simplificação: marcando como coberto.
}
}
}
// Verifica se todos os pontos estão cobertos
for (int i = 1; i <= n; ++i) {
if (current_coverage[i] == 0) return false;
}
return true;
}
void solve() {
std::cin >> n >> s;
// Adiciona padding para facilitar os cálculos de limites
s = " " + s + " ";
int low = 0, high = n;
int min_len = n + 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (check(mid)) {
high = mid - 1;
min_len = mid;
} else {
low = mid + 1;
}
}
std::cout << min_len << std::endl;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int T = 1;
std::cin >> T;
while (T--) {
solve();
}
return 0;
}
</int></int></algorithm></string></vector></iostream>
E - Comprar e Deletar
A estratégia aqui envolve analisar os custos das arestas em relação a um valor c. Se todas as arestas tiverem custo maior que c, nenhuma pode ser comprada, resultando em 0. Se for possível formar um ciclo onde a soma dos custos das arestas é menor ou igual a c, a resposta é 2. Caso contrário, se alguma aresta puder ser comprada individualmente (custo <= c) mas não formar um ciclo favorável, a resposta é 1. O problema é resolvido calculando todas as distâncias par-a-par usando Floyd-Warshall ou múltiplos Dijkstra e verificando a condição do ciclo.
#include <iostream>
#include <vector>
#include <queue>
#include <limits>
const int INF = std::numeric_limits<int>::max();
const int MAXN = 2010;
struct Edge {
int to;
int weight;
};
std::vector<:vector>> adj;
std::vector<:vector>> dist;
int n_nodes, m_edges, cost_threshold;
void run_dijkstra(int start_node) {
dist[start_node][start_node] = 0;
std::priority_queue<:pair int="">, std::vector<:pair int="">>, std::greater<:pair int="">>> pq;
pq.push({0, start_node});
while (!pq.empty()) {
auto [d, u] = pq.top();
pq.pop();
if (d > dist[start_node][u]) {
continue;
}
for (const auto& edge : adj[u]) {
int v = edge.to;
int weight = edge.weight;
if (dist[start_node][u] + weight < dist[start_node][v]) {
dist[start_node][v] = dist[start_node][u] + weight;
pq.push({dist[start_node][v], v});
}
}
}
}
void solve() {
std::cin >> n_nodes >> m_edges >> cost_threshold;
adj.assign(n_nodes + 1, std::vector<edge>());
dist.assign(n_nodes + 1, std::vector<int>(n_nodes + 1, INF));
bool can_buy_any_edge = false;
for (int i = 0; i < m_edges; ++i) {
int u, v, w;
std::cin >> u >> v >> w;
adj[u].push_back({v, w});
adj[v].push_back({u, w}); // Assumindo grafo não direcionado para ciclos
if (w <= cost_threshold) {
can_buy_any_edge = true;
}
}
if (!can_buy_any_edge) {
std::cout << 0 << std::endl;
return;
}
// Calcula todas as distâncias par-a-par
for (int i = 1; i <= n_nodes; ++i) {
run_dijkstra(i);
}
// Verifica a condição do ciclo
for (int i = 1; i <= n_nodes; ++i) {
for (int j = 1; j <= n_nodes; ++j) {
if (i != j && dist[i][j] != INF && dist[j][i] != INF) {
// Verifica se o custo para ir de i para j e voltar para i é <= c
// A lógica original verificava dist[i][j] + dist[j][i] <= c.
// Precisamos considerar o custo direto das arestas se elas forem menores que c.
// Se houver uma aresta (u,v) com peso w <= c, isso conta como resposta 1.
// Se houver um ciclo i -> ... -> j -> ... -> i com custo total <= c, isso conta como 2.
// A implementação original apenas verifica a soma das distâncias.
// Verificando se o caminho de volta é possível com custo total <= c
// Isso pode indicar um ciclo com custo total <= c
if (dist[i][j] + dist[j][i] <= cost_threshold) {
std::cout << 2 << std::endl;
return;
}
}
}
}
// Se não houver ciclo com custo <= c, mas pudemos comprar alguma aresta
std::cout << 1 << std::endl;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int T = 1;
// std::cin >> T; // Aparentemente, apenas um caso de teste é executado.
while (T--) {
solve();
}
return 0;
}
</int></edge></:pair></:pair></:pair></:vector></:vector></int></limits></queue></vector></iostream>
D - A Suposição é Tudo o Que Você Precisa
A estratégia para este problema é processar os elementos do maior para o menor (de n a 1). Para cada elemento i, encontramos suas posições nas arrays a e b (l e r). Se r < l, é impossível satisfazer a condição, e a resposta é -1. Caso contrário, o objetivo é mover o elemento i na array a para a posição r. A estratégia gulosa é, a cada passo, encontrar o maior elemento menor que i no intervalo atual [l, r] e trocá-lo com o elemento na posição l para aproximar l de r. Se l e r não forem iguais, uma troca final é realizada.
#include <iostream>
#include <vector>
#include <utility> // Para std::pair
#include <algorithm> // Para std::swap, std::max
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; ++i) std::cin >> a[i];
for (int i = 1; i <= n; ++i) std::cin >> b[i];
std::vector<:pair int="">> operations;
std::vector<int> pos_a(n + 1); // Guarda a posição atual de cada número em 'a'
// Inicializa as posições
for(int i = 1; i <= n; ++i) pos_a[a[i]] = i;
for (int current_max = n; current_max >= 1; --current_max) {
int target_pos = -1;
// Encontra a posição de 'current_max' em 'b'
for(int j = 1; j <= n; ++j) {
if (b[j] == current_max) {
target_pos = j;
break;
}
}
int current_pos_in_a = pos_a[current_max];
// Se a posição em 'a' já é a posição alvo em 'b', ótimo.
if (current_pos_in_a == target_pos) {
continue;
}
// Se a posição alvo em 'b' está antes da posição atual em 'a', é impossível.
if (target_pos < current_pos_in_a) {
std::cout << -1 << std::endl;
return;
}
// Move o elemento 'current_max' de 'a' para 'target_pos'
// A estratégia é trocar com o maior elemento menor que 'current_max'
// que está entre a posição atual e a posição alvo.
// Encontra o maior elemento menor que current_max no intervalo [current_pos_in_a, target_pos]
int max_smaller_val = 0;
int swap_idx = -1;
for (int k = current_pos_in_a; k <= target_pos; ++k) {
if (a[k] < current_max && a[k] > max_smaller_val) {
max_smaller_val = a[k];
swap_idx = k;
}
}
// Se encontramos um elemento para trocar
if (swap_idx != -1) {
// Trocamos 'current_max' com o elemento 'max_smaller_val'
operations.push_back({current_pos_in_a, swap_idx});
// Atualiza as posições na array 'a'
pos_a[a[current_pos_in_a]] = swap_idx;
pos_a[a[swap_idx]] = current_pos_in_a;
// Realiza a troca na array 'a'
std::swap(a[current_pos_in_a], a[swap_idx]);
// Atualiza a posição atual de current_max
current_pos_in_a = swap_idx;
}
// Agora, current_pos_in_a (que agora é swap_idx) deve ser movido para target_pos
// Se eles ainda não são os mesmos, realiza a troca final.
if (current_pos_in_a != target_pos) {
operations.push_back({current_pos_in_a, target_pos});
// Atualiza posições
pos_a[a[current_pos_in_a]] = target_pos;
pos_a[a[target_pos]] = current_pos_in_a;
std::swap(a[current_pos_in_a], a[target_pos]);
// A posição de current_max agora é target_pos
pos_a[current_max] = target_pos;
} else {
// Se já estava na posição correta após a primeira troca
pos_a[current_max] = target_pos;
}
}
std::cout << operations.size() << std::endl;
for (const auto& op : operations) {
std::cout << op.first << " " << op.second << std::endl;
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int T = 1;
std::cin >> T;
while (T--) {
solve();
}
return 0;
}
</int></:pair></int></algorithm></utility></vector></iostream>
B - Problema A Plus B
Este problema parece ser uma variação do clássico "A + B", mas com strings e possibly operações de bit ou manipulação de dígitos. A solução usa um array de bits e um set para manter posições "interessantes". A lógica parece complexa, envolvendo a soma de dígitos em posições específicas e a manipulação de um estado com base em operações de consulta (q). A condição bit[0][c] + bit[1][c] != 9 e as operações no set path sugerem que o problema lida com a soma de dois números representados como strings, possivelmente com alguma regra especial quando a soma dos dígitos em uma coluna é 9.
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm> // Para std::max, std::prev
// Usaremos long long para garantir que não haja overflow em cálculos intermediários
using ll = long long;
void solve() {
int n; // Comprimento das strings
int q; // Número de queries
std::cin >> n >> q;
std::string s[2];
std::cin >> s[0] >> s[1];
// `bits[i][j]` armazena o dígito na linha `i` e coluna `j+1` (ajuste para 1-based)
std::vector<:vector>> bits(2, std::vector<int>(n + 1, 0));
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < n; ++j) {
bits[i][j + 1] = s[i][j] - '0';
}
}
// `path` armazena as colunas onde a soma dos dígitos não é 9.
// Isso é crucial para o cálculo de "carry" ou "dívida".
std::set<int> path;
path.insert(0); // Limite esquerdo
path.insert(n + 1); // Limite direito
for (int j = 1; j <= n; ++j) {
if (bits[0][j] + bits[1][j] != 9) {
path.insert(j);
}
}
while (q--) {
int r, c, d; // Linha, Coluna, Novo dígito
std::cin >> r >> c >> d;
r--; // Ajusta para 0-based index
// Verifica se a coluna 'c' era 'especial' antes da mudança
bool was_special = (bits[0][c] + bits[1][c] != 9);
if (was_special) {
path.erase(c);
}
// Armazena o resultado da soma na coluna 'c' após a mudança
bits[r][c] = d;
bool is_now_special = (bits[0][c] + bits[1][c] != 9);
// Calcula o "carry" ou "dívida" a partir da coluna 'c'
int next_special_col = *path.lower_bound(c); // O próximo elemento no set >= c
// Calcula o "carry" baseado na soma na coluna atual e na próxima coluna especial
// A lógica `(bits[0][next_special_col] + bits[1][next_special_col] > 9)` parece complexa
// e pode depender de uma regra específica do problema não totalmente clara aqui.
// Vamos tentar replicar a lógica original.
int carry_c = (bits[0][c] + bits[1][c]) % 10; // Soma da coluna atual
int carry_next_special = 0;
if (next_special_col <= n) { // Verifica se next_special_col é válido
// A lógica original tinha `bit[0][t]+bit[1][t]>9`, assumindo que t é a próxima coluna.
// Se a soma na próxima coluna especial for > 9, isso contribui.
carry_next_special = (bits[0][next_special_col] + bits[1][next_special_col]) > 9 ? 1 : 0;
}
int total_sum_at_c = bits[0][c] + bits[1][c]; // Soma original na coluna c
int new_digit_at_c = total_sum_at_c % 10; // Novo dígito na coluna c
// Calcula o resultado da soma na coluna 'c'
int result_c = (bits[0][c] + bits[1][c]) % 10;
// Determina o valor 'res'
int res = 0;
// Se o dígito na linha 'r', coluna 'c' foi alterado E a soma na coluna 'c' mudou
// A condição `bit[r][c] != d` já foi tratada pela atualização de `bits[r][c]`.
// A condição `bit[0][c] + bit[1][c] + (bit[0][t]+bit[1][t]>9)>9` parece ser a chave.
// Vamos simplificar e usar a lógica que parece mais provável:
// Se a soma na coluna 'c' mais o carry da próxima coluna especial for > 9.
int effective_sum_at_c = bits[0][c] + bits[1][c];
if (effective_sum_at_c > 9) { // Se a soma na coluna atual excede 9
// Verifica se a coluna 'c' ainda é especial ou se tornou especial
if (is_now_special) {
// O número de operações é a distância até a próxima coluna especial
int prev_special_col = *std::prev(path.lower_bound(c)); // O elemento antes de c
res += (c - prev_special_col);
}
}
std::cout << result_c << " "; // Imprime o dígito resultante na coluna 'c'
// Verifica se `res` deve ser adicionado e imprime
// A lógica original para adicionar `res` é complexa. Vamos seguir a estrutura:
// Se a soma `bit[0][c] + bit[1][c] + (carry_from_next_special)` for maior que 9
// Isso significa que houve um "transbordamento" para a próxima coluna.
int final_carry_check = bits[0][c] + bits[1][c];
if (next_special_col <= n) { // Se existe uma próxima coluna especial
final_carry_check += (bits[0][next_special_col] + bits[1][next_special_col] > 9);
}
if (final_carry_check > 9) {
// A lógica para adicionar `res` parece ser:
// se a coluna 'c' é agora 'especial' (soma != 9) e houve um transbordamento.
// Ou se a coluna 'c' não era especial mas agora é especial E houve transbordamento.
// O código original usava `flag`. Vamos tentar replicar a condição do `flag`.
// `flag` é trocado se a condição `bit[0][c] + bit[1][c] + (bit[0][t]+bit[1][t]>9)>9` muda.
int previous_state_check = (was_special ? (bits[0][c] + bits[1][c] - (d - bits[r][c])) : 0) ; // Estimativa
if (was_special) { // Se a coluna era especial antes
// Simula o estado anterior. Se o valor anterior era `d_old`, a soma era `old_sum`.
// A condição `old_sum > 9` é o que importa.
previous_state_check = (bits[0][c] + bits[1][c] - (d - (bits[r][c]))) > 9; // Aproximado
} else {
previous_state_check = 0; // Se não era especial, o estado anterior não contribuía para o flag
}
int current_state_check = (bits[0][c] + bits[1][c] > 9);
if (next_special_col <= n) {
current_state_check += (bits[0][next_special_col] + bits[1][next_special_col] > 9);
}
if (previous_state_check != current_state_check) {
// Calcula o `res` corretamente baseado na distância
int prev_special_col = *std::prev(path.lower_bound(c));
res = c - prev_special_col;
} else {
res = 0; // Se o estado não mudou, não adiciona nada.
}
} else {
res = 0; // Se não houve transbordamento, res é 0.
}
std::cout << res << std::endl;
// Se a coluna 'c' agora é especial, adiciona de volta ao path
if (is_now_special) {
path.insert(c);
}
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int T = 1;
// std::cin >> T; // Assumindo um caso de teste
while (T--) {
solve();
}
return 0;
}
</int></int></:vector></algorithm></set></string></vector></iostream>