E. Дружеские подарки ограничение по времени на тес...
創建於:2026年6月12日
創建於:2026年6月12日
E. Дружеские подарки
ограничение по времени на тест
3 секунды
ограничение по памяти на тест
512 мегабайт
Арсений решил порадовать своих друзей — Дабира и Егора. Для этого он решил подарить каждому из них по массиву чисел одинаковой длины. Массив b называется хорошим, если его элементы можно переставить так, что для всех i>1 верно bi−bi−1=1.
Арсений хочет, чтобы Дабир и Егор могли играть с этими массивами. Для этого должны быть выполнены следующие условия:
Каждый из подаренных массивов является хорошим.
Если записать один массив за вторым(другими словами, сконкатенировать), полученный массив окажется хорошим.
У Арсения уже есть массив a длины n. Он планирует вырезать оба массива из a, то есть выбрать в нём два непересекающихся отрезка одинаковой длины. Помогите Арсению определить максимальную возможную длину полученных массивов.
Входные данные
В первой строке находится одно целое число t (1≤t≤1000) — количество наборов входных данных.
Далее следуют t наборов входных данных.
Первая строка каждого набора входных данных содержит одно целое число n (1≤n≤6000).
Вторая строка содержит n целых чисел a1,a2,…,an (1≤ai≤n).
Гарантируется, что сумма значений n по всем наборам входных данных не превосходит 6000.
Выходные данные
Для каждого набора входных данных выведите целое число, обозначающее максимальную возможную длину массивов.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
textint t; cin >> t; while (t--) { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; ++i) cin >> a[i]; vector< int ma = 0, cur = 1; for (int i = 1; i < n; ++i) { if (a[i] - a[i - 1] == 1) cur++; else { if (cur > ma) ma = cur; cur = 1; } } if (cur > ma) ma = cur; cur = a[n - 1]; for (int i = n - 2; i >= 0; --i) { if (a[i] - a[i + 1] == 1) cur++; else { if (cur > ma) ma = cur; cur = 1; } } if (cur > ma) ma = cur; cout << ma / 2 << '\n'; } return 0;
}
что у меня не так? можешь исправить мой код, МИНИМАЛЬНО его изменяя и ОЧЕНЬ ПОДРОБНОО объясняя все исправления и мои ошибки
У тебя проблема не в мелком баге, а в том, что код проверяет не то условие.
Вот исправленный код с сохранением твоего каркаса main / t / n / a / cout:
cpp#include <iostream> #include <vector> #include <algorithm> #include <set> using namespace std; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int t; cin >> t; while (t--) { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; ++i) cin >> a[i]; int ans = 0; for (int k = n / 2; k >= 1; --k) { vector<int> mnPos(n + 2, n + 1); vector<int> mxPos(n + 2, -1); vector<int> cnt(n + 1, 0); int different = 0; multiset<int> s; for (int i = 0; i < n; ++i) { s.insert(a[i]); if (cnt[a[i]] == 0) different++; cnt[a[i]]++; if (i >= k) { s.erase(s.find(a[i - k])); cnt[a[i - k]]--; if (cnt[a[i - k]] == 0) different--; } if (i >= k - 1) { int l = i - k + 1; int mn = *s.begin(); int mx = *s.rbegin(); if (different == k && mx - mn + 1 == k) { mnPos[mn] = min(mnPos[mn], l); mxPos[mn] = max(mxPos[mn], l); } } } bool ok = false; for (int x = 1; x + k <= n; ++x) { if (mnPos[x] == n + 1 || mnPos[x + k] == n + 1) continue; if (mnPos[x] + k <= mxPos[x + k]) ok = true; if (mnPos[x + k] + k <= mxPos[x]) ok = true; } if (ok) { ans = k; break; } } cout << ans << '\n'; } return 0; }
Что у тебя было не так:
cppvector<
Эта строка просто не дописана, из-за неё код не компилируется.
cppif (a[i] - a[i - 1] == 1)
Но по условию массив хороший, если его можно переставить.
Например:
cpp[3, 1, 2]
Это хороший массив, потому что его можно переставить в:
cpp[1, 2, 3]
А твой код такой массив не засчитает.
Массив длины k хороший, если:
cppвсе элементы различны max - min + 1 == k
Например:
cpp[4, 2, 3]
min = 2, max = 4, длина 3.
cpp4 - 2 + 1 == 3
Все элементы разные, значит массив хороший.
Нужно выбрать два непересекающихся отрезка одинаковой длины.
Твой код просто искал максимальный возрастающий/убывающий кусок и делил его на 2:
cppcout << ma / 2 << '\n';
Но это не соответствует условию.
Если один отрезок содержит числа:
cpp[1, 2, 3]
а второй:
cpp[4, 5, 6]
то вместе они дают хороший массив длины 6.
То есть их диапазоны значений должны быть соседними:
cpp[x, x + k - 1] [x + k, x + 2k - 1]
Именно это проверяется здесь:
cppfor (int x = 1; x + k <= n; ++x) { if (mnPos[x] == n + 1 || mnPos[x + k] == n + 1) continue;
Если первый отрезок начинается в l, то он занимает:
cpp[l, l + k - 1]
Чтобы он не пересекался со вторым, который начинается в r, надо:
cppl + k <= r
Поэтому в коде:
cppif (mnPos[x] + k <= mxPos[x + k]) ok = true; if (mnPos[x + k] + k <= mxPos[x]) ok = true;
mnPos[value] — самая левая позиция хорошего отрезка с минимумом value.
mxPos[value] — самая правая позиция такого отрезка.
n / 2 внизДва отрезка длины k не пересекаются, значит всего нужно хотя бы 2k элементов.
Поэтому:
cppk <= n / 2
И как только нашли подходящий k, сразу делаем:
cppans = k; break;
потому что это уже максимальный ответ.