Prueba escrita de Lenovo 811
Tema 1
Ingrese una cadena de longitud n que contenga solo letras en inglés y el subíndice comienza en 1. Realiza las siguientes operaciones en esta cadena Q veces, y la i-ésima operación es la siguiente:
l_i, r_i, k, lo que significa copiar la cadena original con el subíndice l_i, l_i + 1, ..., r_i; después de eso: si k= 0, pégalo al principio de la cadena; si k=1, pégalo al final de la cadena.
Debe generar la cadena obtenida después de las operaciones Q.
Descripción de entrada
La primera línea contiene dos números enteros positivos n, Q (1 es menor o igual que n, Q es menor o igual que 2x10^4).
La segunda línea es una cadena de longitud n que contiene solo letras en inglés.
La tercera línea contiene Q enteros positivos: l_1, l_2, ..., l_Q; la
cuarta línea contiene Q enteros positivos: r_1, r_2, ..., r_Q; la
quinta línea contiene Q enteros positivos: k_1, k_2, .. ., k_Q.
Garantía de datos: 1 es menor o igual que l_i es menor o igual que r_i es menor o igual que n, 0 es menor o igual que r_i-l_i <10, k_i pertenece a {0,1} y el el rango de entrada es legal.
Descripción de salida
Genera una línea, indicando la cadena final.
Entrada de muestra
7 2
Xabcdez
2 1
4 7
0 1
Salida de muestra
abcXabcdezXabcdez
#include <iostream>
#include <string>
#include <vector>
int main() {
int n, q;
std::cin >> n >> q; // 输入字符串长度n和操作次数q
std::string original_str;
std::cin >> original_str; // 输入原始字符串
std::vector<int> l_values(q);
std::vector<int> r_values(q);
std::vector<int> k_values(q);
for (int i = 0; i < q; ++i) {
std::cin >> l_values[i]; // 输入每次操作的起始下标l
}
for (int i = 0; i < q; ++i) {
std::cin >> r_values[i]; // 输入每次操作的结束下标r
}
for (int i = 0; i < q; ++i) {
std::cin >> k_values[i]; // 输入每次操作的粘贴位置k
}
std::string result = original_str; // 初始化结果字符串为原始字符串
for (int i = 0; i < q; ++i) {
int l = l_values[i];
int r = r_values[i];
int k = k_values[i];
// 从原始字符串中复制指定范围的子串
std::string copied_str = original_str.substr(l - 1, r - l + 1);
if (k == 0) {
// 如果粘贴位置k为0,则将复制的子串粘贴在结果字符串的前面
result = copied_str + result;
} else {
// 如果粘贴位置k为1,则将复制的子串粘贴在结果字符串的末尾
result = result + copied_str;
}
}
std::cout << result << std::endl; // 输出最终得到的字符串
return 0;
}
Tema 2
Defina f(A) para representar el número de elementos en la secuencia después de realizar la operación única en la secuencia A.
La operación única se refiere a la secuencia obtenida al combinar elementos adyacentes e idénticos en un solo elemento y luego organizarlos en el orden relativo de la secuencia original.
Por ejemplo,
[1,1,1,2,2,3,3,1] después de la secuencia de operación única es [1,2,3,1]; [1,2,3,3,2,1] El la secuencia después de la operación única es [1,2,3,2,1]; [1,1,1,1,1] la secuencia obtenida después de la operación única es [1].
Ahora, ingrese una secuencia S de longitud n, debe dividirla en k segmentos para que cada segmento no esté vacío y debe maximizar la suma de los valores de la función f de todos los segmentos. Solo necesita generar este valor máximo.
Descripción de entrada
La primera línea son dos enteros positivos n, k (1 es menor o igual que k es menor o igual a la quinta potencia de n es menor o igual a 10); la segunda línea son n enteros positivos a_1
, a_2...a_n separados por espacios (1 es menor o igual que a_i es menor o igual a 10000), que representa la secuencia de entrada S.
Descripción de salida
Genera un número entero que representa el valor máximo buscado.
Entrada de muestra
8 3
1 1 1 2 2 3 3 1
Salida de muestra
6
Explicación de muestra
Dividido de la siguiente manera:
[1], [1 1 2 2 3], [3 1]
El valor de la función del primer párrafo es 1 y la función valor del primer párrafo El valor de la función del segundo segmento es 3 y el valor de la función del tercer segmento es 2, sumando 6. Se puede demostrar que no existe mayor esquema que éste.
Idea:
programación dinámica
Usando dos capas de bucles, el bucle exterior atraviesa todos los elementos y el bucle interior atraviesa todos los números de segmento posibles. En el bucle interno, considere dividir los primeros p elementos en segmentos j-1 y los elementos restantes como el segmento j. Para encontrar el esquema de partición más grande, usamos una variable maxVal para registrar la suma de los valores f de cada partición posible y actualizamos el valor máximo a dp [i] [j] después de que finaliza el ciclo interno.
Finalmente, la salida dp[n][k] es el valor máximo buscado, que indica la suma de los valores máximos de f cuando toda la secuencia se divide en k segmentos.
La función f se utiliza para calcular el número de elementos de la secuencia después de la operación única, su función en el código es calcular el valor f de cada división, ayudando así al cálculo de la programación dinámica.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 定义函数 f,计算序列 segment 经过 unique 操作后的元素个数
int f(const vector<int>& segment) {
vector<int> uniqueSegment;
for (int i = 0; i < segment.size(); ++i) {
if (i == 0 || segment[i] != segment[i - 1]) {
uniqueSegment.push_back(segment[i]);
}
}
return uniqueSegment.size();
}
int main() {
int n, k;
cin >> n >> k; // 输入序列长度 n 和划分段数 k
vector<int> sequence(n);
for (int i = 0; i < n; ++i) {
cin >> sequence[i]; // 输入序列的元素
}
// 使用动态规划,dp[i][j] 表示前 i 个元素划分为 j 段时的最大值
vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= k; ++j) {
int maxVal = 0;
vector<int> segment;
for (int p = i; p >= 1; --p) {
segment.push_back(sequence[p - 1]);
// 在前 p-1 个元素划分为 j-1 段的基础上,加上当前划分的段的 f 值
maxVal = max(maxVal, dp[p - 1][j - 1] + f(segment));
}
dp[i][j] = max(dp[i][j], maxVal); // 更新 dp[i][j]
}
}
cout << dp[n][k] << endl; // 输出最大值
return 0;
}