[{"data":1,"prerenderedAt":6086},["ShallowReactive",2],{"navigation":3,"\u002Fblog\u002Fpython\u002Fst25":386,"\u002Fblog\u002Fpython\u002Fst25-surround":6081},[4],{"title":5,"path":6,"stem":7,"children":8,"page":114},"Blog","\u002Fblog","blog",[9,115,184,329],{"title":10,"path":11,"stem":12,"children":13,"page":114},"Ege","\u002Fblog\u002Fege","blog\u002Fege",[14,18,22,26,30,34,38,42,46,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110],{"title":15,"path":16,"stem":17},"ЕГЭ Задание 1","\u002Fblog\u002Fege\u002Ftask1","blog\u002Fege\u002Ftask1",{"title":19,"path":20,"stem":21},"ЕГЭ Задание 10","\u002Fblog\u002Fege\u002Ftask10","blog\u002Fege\u002Ftask10",{"title":23,"path":24,"stem":25},"ЕГЭ Задание 11","\u002Fblog\u002Fege\u002Ftask11","blog\u002Fege\u002Ftask11",{"title":27,"path":28,"stem":29},"ЕГЭ Задание 12","\u002Fblog\u002Fege\u002Ftask12","blog\u002Fege\u002Ftask12",{"title":31,"path":32,"stem":33},"ЕГЭ Задание 13","\u002Fblog\u002Fege\u002Ftask13","blog\u002Fege\u002Ftask13",{"title":35,"path":36,"stem":37},"ЕГЭ Задание 14","\u002Fblog\u002Fege\u002Ftask14","blog\u002Fege\u002Ftask14",{"title":39,"path":40,"stem":41},"ЕГЭ Задание 15","\u002Fblog\u002Fege\u002Ftask15","blog\u002Fege\u002Ftask15",{"title":43,"path":44,"stem":45},"ЕГЭ Задание 16","\u002Fblog\u002Fege\u002Ftask16","blog\u002Fege\u002Ftask16",{"title":47,"path":48,"stem":49},"ЕГЭ Задание 17","\u002Fblog\u002Fege\u002Ftask17","blog\u002Fege\u002Ftask17",{"title":51,"path":52,"stem":53},"ЕГЭ Задание 18","\u002Fblog\u002Fege\u002Ftask18","blog\u002Fege\u002Ftask18",{"title":55,"path":56,"stem":57},"ЕГЭ Задание 19, 20, 21","\u002Fblog\u002Fege\u002Ftask19_20_21","blog\u002Fege\u002Ftask19_20_21",{"title":59,"path":60,"stem":61},"ЕГЭ Задание 2","\u002Fblog\u002Fege\u002Ftask2","blog\u002Fege\u002Ftask2",{"title":63,"path":64,"stem":65},"ЕГЭ Задание 22","\u002Fblog\u002Fege\u002Ftask22","blog\u002Fege\u002Ftask22",{"title":67,"path":68,"stem":69},"ЕГЭ Задание 23","\u002Fblog\u002Fege\u002Ftask23","blog\u002Fege\u002Ftask23",{"title":71,"path":72,"stem":73},"ЕГЭ Задание 24","\u002Fblog\u002Fege\u002Ftask24","blog\u002Fege\u002Ftask24",{"title":75,"path":76,"stem":77},"ЕГЭ Задание 25","\u002Fblog\u002Fege\u002Ftask25","blog\u002Fege\u002Ftask25",{"title":79,"path":80,"stem":81},"ЕГЭ Задание 26","\u002Fblog\u002Fege\u002Ftask26","blog\u002Fege\u002Ftask26",{"title":83,"path":84,"stem":85},"ЕГЭ Задание 27","\u002Fblog\u002Fege\u002Ftask27","blog\u002Fege\u002Ftask27",{"title":87,"path":88,"stem":89},"ЕГЭ Задание 3","\u002Fblog\u002Fege\u002Ftask3","blog\u002Fege\u002Ftask3",{"title":91,"path":92,"stem":93},"ЕГЭ Задание 4","\u002Fblog\u002Fege\u002Ftask4","blog\u002Fege\u002Ftask4",{"title":95,"path":96,"stem":97},"ЕГЭ Задание 5","\u002Fblog\u002Fege\u002Ftask5","blog\u002Fege\u002Ftask5",{"title":99,"path":100,"stem":101},"ЕГЭ Задание 6","\u002Fblog\u002Fege\u002Ftask6","blog\u002Fege\u002Ftask6",{"title":103,"path":104,"stem":105},"ЕГЭ Задание 7","\u002Fblog\u002Fege\u002Ftask7","blog\u002Fege\u002Ftask7",{"title":107,"path":108,"stem":109},"ЕГЭ Задание 8","\u002Fblog\u002Fege\u002Ftask8","blog\u002Fege\u002Ftask8",{"title":111,"path":112,"stem":113},"ЕГЭ Задание 9","\u002Fblog\u002Fege\u002Ftask9","blog\u002Fege\u002Ftask9",false,{"title":116,"path":117,"stem":118,"children":119,"page":114},"Oge","\u002Fblog\u002Foge","blog\u002Foge",[120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180],{"title":121,"path":122,"stem":123},"ОГЭ Задание 1","\u002Fblog\u002Foge\u002Ftask1","blog\u002Foge\u002Ftask1",{"title":125,"path":126,"stem":127},"ОГЭ Задание 10","\u002Fblog\u002Foge\u002Ftask10","blog\u002Foge\u002Ftask10",{"title":129,"path":130,"stem":131},"ОГЭ Задание 11","\u002Fblog\u002Foge\u002Ftask11","blog\u002Foge\u002Ftask11",{"title":133,"path":134,"stem":135},"ОГЭ Задание 12","\u002Fblog\u002Foge\u002Ftask12","blog\u002Foge\u002Ftask12",{"title":137,"path":138,"stem":139},"ОГЭ Задание 13","\u002Fblog\u002Foge\u002Ftask13","blog\u002Foge\u002Ftask13",{"title":141,"path":142,"stem":143},"ОГЭ Задание 14","\u002Fblog\u002Foge\u002Ftask14","blog\u002Foge\u002Ftask14",{"title":145,"path":146,"stem":147},"ОГЭ Задание 15","\u002Fblog\u002Foge\u002Ftask15","blog\u002Foge\u002Ftask15",{"title":149,"path":150,"stem":151},"ОГЭ Задание 16","\u002Fblog\u002Foge\u002Ftask16","blog\u002Foge\u002Ftask16",{"title":153,"path":154,"stem":155},"ОГЭ Задание 2","\u002Fblog\u002Foge\u002Ftask2","blog\u002Foge\u002Ftask2",{"title":157,"path":158,"stem":159},"ОГЭ Задание 3","\u002Fblog\u002Foge\u002Ftask3","blog\u002Foge\u002Ftask3",{"title":161,"path":162,"stem":163},"ОГЭ Задание 4","\u002Fblog\u002Foge\u002Ftask4","blog\u002Foge\u002Ftask4",{"title":165,"path":166,"stem":167},"ОГЭ Задание 5","\u002Fblog\u002Foge\u002Ftask5","blog\u002Foge\u002Ftask5",{"title":169,"path":170,"stem":171},"ОГЭ Задание 6","\u002Fblog\u002Foge\u002Ftask6","blog\u002Foge\u002Ftask6",{"title":173,"path":174,"stem":175},"ОГЭ Задание 7","\u002Fblog\u002Foge\u002Ftask7","blog\u002Foge\u002Ftask7",{"title":177,"path":178,"stem":179},"ОГЭ Задание 8","\u002Fblog\u002Foge\u002Ftask8","blog\u002Foge\u002Ftask8",{"title":181,"path":182,"stem":183},"ОГЭ Задание 9","\u002Fblog\u002Foge\u002Ftask9","blog\u002Foge\u002Ftask9",{"title":185,"path":186,"stem":187,"children":188,"page":114},"Python","\u002Fblog\u002Fpython","blog\u002Fpython",[189,193,197,201,205,209,213,217,221,225,229,233,237,241,245,249,253,257,261,265,269,273,277,281,285,289,293,297,301,305,309,313,317,321,325],{"title":190,"path":191,"stem":192},"Знакомство с синтаксисом","\u002Fblog\u002Fpython\u002Fst1","blog\u002Fpython\u002Fst1",{"title":194,"path":195,"stem":196},"Отладка","\u002Fblog\u002Fpython\u002Fst10","blog\u002Fpython\u002Fst10",{"title":198,"path":199,"stem":200},"Модули и пакеты","\u002Fblog\u002Fpython\u002Fst11","blog\u002Fpython\u002Fst11",{"title":202,"path":203,"stem":204},"Кортежи","\u002Fblog\u002Fpython\u002Fst12","blog\u002Fpython\u002Fst12",{"title":206,"path":207,"stem":208},"Знакомство со списками","\u002Fblog\u002Fpython\u002Fst13","blog\u002Fpython\u002Fst13",{"title":210,"path":211,"stem":212},"Списки и циклы","\u002Fblog\u002Fpython\u002Fst14","blog\u002Fpython\u002Fst14",{"title":214,"path":215,"stem":216},"Использование списков ч.1","\u002Fblog\u002Fpython\u002Fst15","blog\u002Fpython\u002Fst15",{"title":218,"path":219,"stem":220},"Использование списков ч.2","\u002Fblog\u002Fpython\u002Fst16","blog\u002Fpython\u002Fst16",{"title":222,"path":223,"stem":224},"Использование списков ч.3","\u002Fblog\u002Fpython\u002Fst17","blog\u002Fpython\u002Fst17",{"title":226,"path":227,"stem":228},"Словари","\u002Fblog\u002Fpython\u002Fst18","blog\u002Fpython\u002Fst18",{"title":230,"path":231,"stem":232},"Множества","\u002Fblog\u002Fpython\u002Fst19","blog\u002Fpython\u002Fst19",{"title":234,"path":235,"stem":236},"Переменные","\u002Fblog\u002Fpython\u002Fst2","blog\u002Fpython\u002Fst2",{"title":238,"path":239,"stem":240},"Хеш-таблицы","\u002Fblog\u002Fpython\u002Fst20","blog\u002Fpython\u002Fst20",{"title":242,"path":243,"stem":244},"Решето Эратосфена","\u002Fblog\u002Fpython\u002Fst21","blog\u002Fpython\u002Fst21",{"title":246,"path":247,"stem":248},"Длинная арифметика","\u002Fblog\u002Fpython\u002Fst22","blog\u002Fpython\u002Fst22",{"title":250,"path":251,"stem":252},"Декораторы функций","\u002Fblog\u002Fpython\u002Fst23","blog\u002Fpython\u002Fst23",{"title":254,"path":255,"stem":256},"Знакомство с алгоритмами","\u002Fblog\u002Fpython\u002Fst24","blog\u002Fpython\u002Fst24",{"title":258,"path":259,"stem":260},"Бинарный поиск – примеры задач","\u002Fblog\u002Fpython\u002Fst25","blog\u002Fpython\u002Fst25",{"title":262,"path":263,"stem":264},"Сортировка выбором","\u002Fblog\u002Fpython\u002Fst26","blog\u002Fpython\u002Fst26",{"title":266,"path":267,"stem":268},"Рекурсия и стек","\u002Fblog\u002Fpython\u002Fst27","blog\u002Fpython\u002Fst27",{"title":270,"path":271,"stem":272},"Быстрая сортировка","\u002Fblog\u002Fpython\u002Fst28","blog\u002Fpython\u002Fst28",{"title":274,"path":275,"stem":276},"Поиск в ширину","\u002Fblog\u002Fpython\u002Fst29","blog\u002Fpython\u002Fst29",{"title":278,"path":279,"stem":280},"Работа со строками","\u002Fblog\u002Fpython\u002Fst3","blog\u002Fpython\u002Fst3",{"title":282,"path":283,"stem":284},"Поиск в глубину","\u002Fblog\u002Fpython\u002Fst30","blog\u002Fpython\u002Fst30",{"title":286,"path":287,"stem":288},"Сбалансированные деревья","\u002Fblog\u002Fpython\u002Fst31","blog\u002Fpython\u002Fst31",{"title":290,"path":291,"stem":292},"Алгоритм Дейкстры","\u002Fblog\u002Fpython\u002Fst32","blog\u002Fpython\u002Fst32",{"title":294,"path":295,"stem":296},"Жадные алгоритмы","\u002Fblog\u002Fpython\u002Fst33","blog\u002Fpython\u002Fst33",{"title":298,"path":299,"stem":300},"Динамическое программирование","\u002Fblog\u002Fpython\u002Fst34","blog\u002Fpython\u002Fst34",{"title":302,"path":303,"stem":304},"Алгоритм k ближайших соседей","\u002Fblog\u002Fpython\u002Fst35","blog\u002Fpython\u002Fst35",{"title":306,"path":307,"stem":308},"Типы данных","\u002Fblog\u002Fpython\u002Fst4","blog\u002Fpython\u002Fst4",{"title":310,"path":311,"stem":312},"О функциях","\u002Fblog\u002Fpython\u002Fst5","blog\u002Fpython\u002Fst5",{"title":314,"path":315,"stem":316},"Свойства и методы","\u002Fblog\u002Fpython\u002Fst6","blog\u002Fpython\u002Fst6",{"title":318,"path":319,"stem":320},"Определение функций","\u002Fblog\u002Fpython\u002Fst7","blog\u002Fpython\u002Fst7",{"title":322,"path":323,"stem":324},"Логика","\u002Fblog\u002Fpython\u002Fst8","blog\u002Fpython\u002Fst8",{"title":326,"path":327,"stem":328},"Циклы","\u002Fblog\u002Fpython\u002Fst9","blog\u002Fpython\u002Fst9",{"title":330,"path":331,"stem":332,"children":333,"page":114},"Toi","\u002Fblog\u002Ftoi","blog\u002Ftoi",[334,338,342,346,350,354,358,362,366,370,374,378,382],{"title":335,"path":336,"stem":337},"Информация и информационные процессы","\u002Fblog\u002Ftoi\u002Fst1","blog\u002Ftoi\u002Fst1",{"title":339,"path":340,"stem":341},"Электронные таблицы","\u002Fblog\u002Ftoi\u002Fst10","blog\u002Ftoi\u002Fst10",{"title":343,"path":344,"stem":345},"Система, её свойства и компоненты. Моделирование","\u002Fblog\u002Ftoi\u002Fst11","blog\u002Ftoi\u002Fst11",{"title":347,"path":348,"stem":349},"Представление информации в компьютере","\u002Fblog\u002Ftoi\u002Fst12","blog\u002Ftoi\u002Fst12",{"title":351,"path":352,"stem":353},"Средства информационно-коммуникационных технологий. Файловая система","\u002Fblog\u002Ftoi\u002Fst13","blog\u002Ftoi\u002Fst13",{"title":355,"path":356,"stem":357},"Комбинаторика","\u002Fblog\u002Ftoi\u002Fst2","blog\u002Ftoi\u002Fst2",{"title":359,"path":360,"stem":361},"Адресация в интернете","\u002Fblog\u002Ftoi\u002Fst3","blog\u002Ftoi\u002Fst3",{"title":363,"path":364,"stem":365},"Измерение количества информации","\u002Fblog\u002Ftoi\u002Fst4","blog\u002Ftoi\u002Fst4",{"title":367,"path":368,"stem":369},"Системы счисления","\u002Fblog\u002Ftoi\u002Fst5","blog\u002Ftoi\u002Fst5",{"title":371,"path":372,"stem":373},"Диаграммы Эйлера — Венна","\u002Fblog\u002Ftoi\u002Fst6","blog\u002Ftoi\u002Fst6",{"title":375,"path":376,"stem":377},"Условие Фано","\u002Fblog\u002Ftoi\u002Fst7","blog\u002Ftoi\u002Fst7",{"title":379,"path":380,"stem":381},"Теория графов","\u002Fblog\u002Ftoi\u002Fst8","blog\u002Ftoi\u002Fst8",{"title":383,"path":384,"stem":385},"Алгебра логики","\u002Fblog\u002Ftoi\u002Fst9","blog\u002Ftoi\u002Fst9",{"id":387,"title":258,"author":388,"body":393,"date":6072,"description":6073,"extension":6074,"image":6075,"meta":6076,"minRead":6077,"navigation":5707,"num":6078,"path":259,"seo":6079,"stem":260,"__hash__":6080},"python\u002Fblog\u002Fpython\u002Fst25.md",{"name":389,"avatar":390},"Штана Альберт Игоревич",{"src":391,"alt":392},"me.jpg","@ashtana",{"type":394,"value":395,"toc":6026},"minimark",[396,401,409,417,421,425,429,432,435,438,445,448,451,455,458,471,496,499,503,506,510,513,516,519,524,751,754,758,765,771,782,978,1064,1068,1079,1215,1249,1319,1322,1325,1342,1346,1349,1363,1370,1373,1376,1380,1383,1386,1389,1392,1395,1398,1401,1404,1411,1414,1417,1439,1442,1445,1473,1476,1479,1483,1486,1510,1513,1516,1519,1522,1676,1679,1696,1699,1702,1768,1771,1774,1777,1888,1891,1894,1897,1967,1974,1978,1981,1984,2006,2213,2219,2222,2225,2228,2243,2287,2290,2293,2296,2303,2312,2584,2591,2594,2597,2689,2709,2865,2898,3290,3294,3297,3309,3414,3420,3423,3434,3437,3705,3715,3721,3725,3728,3893,3896,3903,3906,3952,3955,4021,4024,4031,4034,4198,4201,4365,4368,4371,4538,4541,4705,4708,5107,5215,5219,5222,5225,5235,5238,5264,5267,5299,5302,5305,5313,5319,5322,5341,5352,5359,5417,5424,5427,5536,5539,5542,5545,5621,5647,5650,5660,5663,5666,5669,5672,5962,5974,5981,5987,6009,6012,6016,6019,6023],[397,398,400],"h2",{"id":399},"примеры-задач-бинарного-поиска","Примеры задач бинарного поиска",[402,403,405],"h5",{"id":404},"рекомендую-изучать-примеры-задач-когда-вы-знаете-также-и-другие-алгоритмы-сортировки-рекурсии-жадные-алгоритмы-алгоритмы-на-графах-динамическое-программирование",[406,407,408],"strong",{},"РЕКОМЕНДУЮ ИЗУЧАТЬ ПРИМЕРЫ ЗАДАЧ КОГДА ВЫ ЗНАЕТЕ ТАКЖЕ И ДРУГИЕ АЛГОРИТМЫ: СОРТИРОВКИ, РЕКУРСИИ, ЖАДНЫЕ АЛГОРИТМЫ, АЛГОРИТМЫ НА ГРАФАХ, ДИНАМИЧЕСКОЕ ПРОГРАММИРОВАНИЕ!",[410,411,413],"h4",{"id":412},"описание-алгоритма-здесь",[414,415,416],"a",{"href":255},"Описание алгоритма здесь",[410,418,420],{"id":419},"задача-1-кормление-муравьев","Задача 1. Кормление муравьев",[402,422,424],{"id":423},"условие","Условие",[426,427,428],"p",{},"У Боби есть террариум в форме дерева. Каждое ребро этого дерева является трубкой, по которой стекает жидкость.\nНекоторые ребра образованы супер трубками, по которым может протекать большее количество жидкости. В каждом листе\n(концевом узле) дерева находится один ручной муравей (согласен, что контекст фантастический, но сама задача очень интересная).",[426,430,431],{},"У каждой трубки-ребра есть значение веса, указывающее процент протекающей по ней жидкости.\nК примеру, из узла n исходят три трубки, по которым стекает 20%, 50% и 30% жидкости от общего объема.\nЕсли в узел n поступает 20 литров жидкости, тогда по первой трубке стекает 20 × 0,2 = 4 литра, по второй 20 × 0,5 = 10 литров, по третьей 20 × 0,3 = 6 литров.",[426,433,434],{},"Каждая супер трубка может работать в стандартном или супер режиме — в зависимости от выбора Боби.\nЕсли включен супер режим, то количество протекающей жидкости возводится в квадрат.",[426,436,437],{},"Боби заливает жидкость в корень дерева. Его цель — дать каждому муравью не меньше необходимого количества, минимизируя при этом заливаемый объем.\nКонкретизируем описание на примере террариума на рисунке.",[426,439,440],{},[441,442],"img",{"alt":443,"src":444},"Задача 1. Условие","\u002Fimages\u002Fblog\u002Fpython\u002Fst25\u002Fimg1.png",[426,446,447],{},"Узлы пронумерованы от 1 до 6. Концевые узлы (2, 3, 5 и 6) имеют дополнительные значения, указывающие необходимое каждому муравью количество жидкости.\nТакже указаны процентные значения для ребер. Обратите внимание, что сумма этих значений для ребер, исходящих из одного узла, всегда равна 100%.\nВ дереве есть одна супер трубка, ведущая из узла 1 к узлу 4. Она обозначена красной линией.",[426,449,450],{},"Предположим, что в корень заливается 20 литров жидкости. Супер трубка получает 30% от 20 литров. Если супер режим этой трубки отключен, то через нее протекает 6 литров.\nЕсли же этот режим активен, то через нее пройдет 6 * 6 = 36 литров.",[402,452,454],{"id":453},"входные-данные","Входные данные",[426,456,457],{},"Входные данные содержат один тестовый пример, состоящий из следующих строк:",[459,460,461,465,468],"ul",{},[462,463,464],"li",{},"целого числа n, задающего количество узлов в дереве. Значение n находится между 1 и 1000. Узлы дерева пронумерованы от 1 до n, а корнем является узел 1;",[462,466,467],{},"(n – 1) строк, используемых для построения дерева. Каждая содержит данные об одной трубке и состоит из четырех целых чисел: номеров двух узлов, соединяемых этой трубкой, ее процентного значения (между 1 и 100) и указания о возможности суперрежима (0 означает отсутствие, 1 — наличие);",[462,469,470],{},"строки, содержащей n целых чисел, по одному для каждого узла, сообщающих количество литров, необходимых муравью в этом узле. Каждому муравью требуется от 1 до 10 литров жидкости. Все не концевые узлы (в которых нет муравья) содержат значение –1.",[426,472,473,474,477,478,480,481,483,484,486,487,489,490,492,493,495],{},"Вот входные данные, которые сгенерируют образец террариума с рисунка выше: ",[475,476],"br",{},"\n6 ",[475,479],{},"\n1 2 20 0 ",[475,482],{},"\n1 3 50 0 ",[475,485],{},"\n1 4 30 1 ",[475,488],{},"\n4 5 50 0 ",[475,491],{},"\n4 6 50 0 ",[475,494],{},"\n-1 2 9 -1 7 8",[426,497,498],{},"Обратите внимание, что первая строка (число 6) указывает количество узлов дерева, а не количество строк, его выстраивающих.\nЧисло строк, создающих дерево(в данном случае пять), всегда будет на единицу меньше числа узлов.",[402,500,502],{"id":501},"выходные-данные","Выходные данные",[426,504,505],{},"Требуется вывести минимальное количество литров жидкости, которое Боби должен залить в корневой узел дерева, чтобы напоить всех муравьев.\nТочность должна быть выше четырех цифр после запятой. Верное значение не будет превышать двух миллиардов.\nВремя на решение тестового примера — 2,5 секунды.",[402,507,509],{"id":508},"решение","Решение",[426,511,512],{},"В данном случае для исследования дерева террариума можно использовать алгоритм бинарного поиска или рекурсию.\nПоскольку дерево не предоставляет необходимую информацию в готовом виде, возьмем значение объема наугад.\nИтак, Боби, давай зальем в корень 10 литров. Вероятно, вас сильно удивит, если верным ответом окажется именно 10, ведь это\nчисло я выбрал наугад. Вас также может удивить, что, выбрав произвольное число и проанализировав происходящее, мы можем многое узнать.\nВернемся к рисунку из условия и предположим, что заливаем в корневой узел 10 литров. Итак, 20% от 10 — это 2, значит, 2 литра жидкости поступят к муравью в узле 2.\nИдеально: именно 2 литра ему и надо. Продолжим. Поскольку 50% от 10 равно 5, то муравей в узле 3 получает 5 литров жидкости.\nВот теперь у нас проблема, потому что ему нужно 9 литров. При этом трубка между узлами 1 и 3 не имеет супер режима, значит, изменить ситуацию нельзя и 10 верным решением не является.\nМожно продолжить подставлять наугад и другие количества жидкости, аналогичным образом моделируя ее течение по дереву.\nИ все же, если 10 литров оказалось недостаточно, теперь следует ограничить диапазон до значений больше 10.\nПоскольку 10 литров было мало, любое меньшее значение также окажется недостаточным. Нет смысла пробовать 2, 7, 9, 5 литров или любое другое количество меньше 10.",[426,514,515],{},"Теперь давайте возьмем 20 литров. На этот раз муравей в узле 2 получает 4 литра, что вполне нормально, так как ему достаточно двух.\nМуравей в узле 3 получает 10 литров, что также допустимо, потому что ему нужно 9.\nТрубка между узлами 1 и 4 проводит 30% жидкости, то есть 6 из 20 литров. Но при этом она еще и является супер трубкой!\nЕсли задействовать супер режим, то она прокачает 36 литров. Значит, в узел 4 протекает 36 литров.\nТеперь муравьи 5 и 6 будут довольны: каждый из них получает по 18 литров при том, что в узел 5 нужно 7, а в узел 6 — 8 литров.\nВ отличие от 10 литров, 20 оказалось допустимым решением, но является ли оно оптимальным (то есть минимальным)? Возможно, но не обязательно.\nОднозначно нам известно лишь то, что проверять количество более 20 литров смысла нет. 20 уже\nдает нам допустимое решение, так зачем пробовать 25 или 30, которые точно хуже?\nТеперь мы сократили область задачи до нахождения оптимального решения между 10 и 20 литрами.\nМожно продолжать подбирать числа, с каждым шагом сужая диапазон, пока он не станет столь мал, что его конечные точки окажутся точным решением.",[426,517,518],{},"Если рассуждать в общем, то какое количество литров следует выбирать изначально? Оптимальный объем может иметь значение вплоть до 2 миллиардов, так\nчто, начиная с 10, можно оказаться очень далеко от истины. Установив начальное значение, что следует делать дальше?\nОптимальное решение может быть значительно больше или меньше выбранного значения, значит, прибавление или вычитание 10 на каждом шаге может не слишком помочь в его поиске.\nСначала нужно разобраться с тем, как считывать входные данные (чтобы иметь возможность исследовать дерево) и определять, является ли некоторое количество литров допустимым решением.\nЗатем построить супер быстрый алгоритм для поиска в больших диапазонах.\nДиапазон в два миллиарда? Мы выполним расчет для него, не напрягаясь с помощью бинарного поиска.",[520,521,523],"h6",{"id":522},"считывание-входных-данных","СЧИТЫВАНИЕ ВХОДНЫХ ДАННЫХ",[525,526,531],"pre",{"className":527,"code":528,"language":529,"meta":530,"style":530},"language-python shiki shiki-themes github-light","nodes = dict()  # Словарь узлов\nN = int(input()) # Количество узлов\nfor i in range(N - 1):\n    from_node, to_node, percentage, superpipe = map(int, input().split())\n    if from_node not in nodes:  # Если узла ещё нет\n        nodes[from_node] = [[], [], []]\n    nodes[from_node][0].append(to_node)\n    nodes[from_node][1].append(percentage)\n    nodes[from_node][2].append(superpipe)\nliquid_needed = list(map(int, input().split()))# Список по узлам конечных значений о количестве нужной каждому муравью жидкости\nprint(nodes) # => {1: [[2, 3, 4], [20, 50, 30], [0, 0, 1]], 4: [[5, 6], [50, 50], [0, 0]]}\nprint(liquid_needed) # => [-1, 2, 9, -1, 7, 8]\n","python","",[532,533,534,558,581,608,632,653,664,676,687,698,728,740],"code",{"__ignoreMap":530},[535,536,539,543,547,551,554],"span",{"class":537,"line":538},"line",1,[535,540,542],{"class":541},"sgsFI","nodes ",[535,544,546],{"class":545},"sD7c4","=",[535,548,550],{"class":549},"sYu0t"," dict",[535,552,553],{"class":541},"()  ",[535,555,557],{"class":556},"sAwPA","# Словарь узлов\n",[535,559,561,564,566,569,572,575,578],{"class":537,"line":560},2,[535,562,563],{"class":541},"N ",[535,565,546],{"class":545},[535,567,568],{"class":549}," int",[535,570,571],{"class":541},"(",[535,573,574],{"class":549},"input",[535,576,577],{"class":541},"()) ",[535,579,580],{"class":556},"# Количество узлов\n",[535,582,584,587,590,593,596,599,602,605],{"class":537,"line":583},3,[535,585,586],{"class":545},"for",[535,588,589],{"class":541}," i ",[535,591,592],{"class":545},"in",[535,594,595],{"class":549}," range",[535,597,598],{"class":541},"(N ",[535,600,601],{"class":545},"-",[535,603,604],{"class":549}," 1",[535,606,607],{"class":541},"):\n",[535,609,611,614,616,619,621,624,627,629],{"class":537,"line":610},4,[535,612,613],{"class":541},"    from_node, to_node, percentage, superpipe ",[535,615,546],{"class":545},[535,617,618],{"class":549}," map",[535,620,571],{"class":541},[535,622,623],{"class":549},"int",[535,625,626],{"class":541},", ",[535,628,574],{"class":549},[535,630,631],{"class":541},"().split())\n",[535,633,635,638,641,644,647,650],{"class":537,"line":634},5,[535,636,637],{"class":545},"    if",[535,639,640],{"class":541}," from_node ",[535,642,643],{"class":545},"not",[535,645,646],{"class":545}," in",[535,648,649],{"class":541}," nodes:  ",[535,651,652],{"class":556},"# Если узла ещё нет\n",[535,654,656,659,661],{"class":537,"line":655},6,[535,657,658],{"class":541},"        nodes[from_node] ",[535,660,546],{"class":545},[535,662,663],{"class":541}," [[], [], []]\n",[535,665,667,670,673],{"class":537,"line":666},7,[535,668,669],{"class":541},"    nodes[from_node][",[535,671,672],{"class":549},"0",[535,674,675],{"class":541},"].append(to_node)\n",[535,677,679,681,684],{"class":537,"line":678},8,[535,680,669],{"class":541},[535,682,683],{"class":549},"1",[535,685,686],{"class":541},"].append(percentage)\n",[535,688,690,692,695],{"class":537,"line":689},9,[535,691,669],{"class":541},[535,693,694],{"class":549},"2",[535,696,697],{"class":541},"].append(superpipe)\n",[535,699,701,704,706,709,711,714,716,718,720,722,725],{"class":537,"line":700},10,[535,702,703],{"class":541},"liquid_needed ",[535,705,546],{"class":545},[535,707,708],{"class":549}," list",[535,710,571],{"class":541},[535,712,713],{"class":549},"map",[535,715,571],{"class":541},[535,717,623],{"class":549},[535,719,626],{"class":541},[535,721,574],{"class":549},[535,723,724],{"class":541},"().split()))",[535,726,727],{"class":556},"# Список по узлам конечных значений о количестве нужной каждому муравью жидкости\n",[535,729,731,734,737],{"class":537,"line":730},11,[535,732,733],{"class":549},"print",[535,735,736],{"class":541},"(nodes) ",[535,738,739],{"class":556},"# => {1: [[2, 3, 4], [20, 50, 30], [0, 0, 1]], 4: [[5, 6], [50, 50], [0, 0]]}\n",[535,741,743,745,748],{"class":537,"line":742},12,[535,744,733],{"class":549},[535,746,747],{"class":541},"(liquid_needed) ",[535,749,750],{"class":556},"# => [-1, 2, 9, -1, 7, 8]\n",[426,752,753],{},"Переменная to_node указывает на дочерний узел, соединенный ребром с родительским. percentage является целым числом между 1 и 100, которое сообщает процентное\nзначение для трубки (ребра). superpipe — флаг, который имеет значение 1, если трубка имеет суперрежим, и 0, если такой режим отсутствует.\nВ частности, каждое ребро считывается из входных данных, затем устанавливаются его члены, после чего оно добавляется в список ребер для from_node.\nПри этом можно было бы предположить существование соответствующего ребра из to_node, потому что граф ненаправленный, но я такую возможность исключил:\nжидкость стекает вниз по дереву, но не вверх, значит, добавление обратных ребер излишне усложнит код, исследующий дерево.\nПосле считывания информации о дереве остается только считать значения количества жидкости, необходимого каждому муравью.\nДля этого используется список liquid_needed.\nКомбинация из nodes и liquid_needed обеспечивает всю необходимую нам информацию на тестовом примере.",[520,755,757],{"id":756},"проверка-пригодности-решения","ПРОВЕРКА ПРИГОДНОСТИ РЕШЕНИЯ",[426,759,760,761,764],{},"На следующем этапе надо определить, является ли заданное количество жидкости допустимым решением.\nЭто очень важный шаг, потому что, когда у нас появится функция для проверки допустимости значения,\nмы сможем использовать ее для постепенного сужения пространства поиска до момента обнаружения оптимального решения.\nДля этой функции мы напишем следующий заголовок: ",[532,762,763],{},"def can_feed(node, liquid, nodes, liquid_needed):",".\nЗдесь node является корневым узлом дерева, liquid указывает количество жидкости, заливаемой в корень, nodes представляет словарь для дерева,\nа liquid_needed отражает объем жидкости, необходимый каждому муравью. Если значения liquid окажется достаточно, будет возвращаться 1, в противном случае 0.",[426,766,767,768],{},"Давайте теперь подумаем, можно ли применить рекурсию в этой задаче.\nВспомним, что для использования рекурсии требуется сформулировать базовый случай, который можно решить без рекурсии.\nК счастью, у нас такой имеется. Если дерево представлено одним концевым узлом, то можно сразу определить, достаточно ли количества liquid.\nЕсли liquid больше либо равно необходимому муравью количеству жидкости, то перед нами допустимое решение.\nВ противном случае решение не допустимое.\nОпределить, является ли узел концевым, можно проверкой соответствующего значения в liquid_needed:\nесли это -1, значит, он не концевой (можно также проверить, является ли связный список смежности пустым).\nВот что получается: ",[532,769,770],{},"if liquid_needed[node] != -1: return liquid >= liquid_needed[node]",[426,772,773,774,777,778,781],{},"А теперь рассмотрим рекурсивный алгоритм. Представьте, что корневой узел некоторого дерева имеет p нисходящих трубок (а значит, и p детей).\nДано количество заливаемой в корень жидкости. Используя процентные значения трубок, можно определить объем жидкости, которая поступает через каждую из них.\nПри этом с помощью статусов супертрубок можно определить количество жидкости на выходе из каждой трубки.\nЕсли до низа трубки доходит достаточный объем питья, то заливаемой в корень жидкости хватает и нужно вернуть ",[532,775,776],{},"True",".\nЕсли до низа хотя бы одной из трубок доходит недостаточный объем жидкости, то возвращается ",[532,779,780],{},"False",".\nЭто предполагает, что нужно сделать p рекурсивных вызовов, по одному для каждой нисходящей из корня трубки.\nСделаем мы это в цикле, использующем словарь для каждой такой трубки:",[525,783,785],{"className":527,"code":784,"language":529,"meta":530,"style":530},"def can_feed(node, liquid, nodes, liquid_needed):\n    if liquid_needed[node - 1] != -1:\n        return liquid >= liquid_needed[node - 1]\n    e = nodes.get(node)\n    if e:\n        for p in range(len(e[0])):\n            down_pipe = liquid * e[1][p] \u002F 100  # e[1] это percentage — процентное значение для трубки\n            if e[2][p]: # если \"супер трубка\"\n                down_pipe *= down_pipe  # 2\n            if not can_feed(e[0][p], down_pipe, nodes, liquid_needed): # 3\n                return False\n    return True\n",[532,786,787,799,824,844,854,861,886,915,930,944,962,970],{"__ignoreMap":530},[535,788,789,792,796],{"class":537,"line":538},[535,790,791],{"class":545},"def",[535,793,795],{"class":794},"s7eDp"," can_feed",[535,797,798],{"class":541},"(node, liquid, nodes, liquid_needed):\n",[535,800,801,803,806,808,810,813,816,819,821],{"class":537,"line":560},[535,802,637],{"class":545},[535,804,805],{"class":541}," liquid_needed[node ",[535,807,601],{"class":545},[535,809,604],{"class":549},[535,811,812],{"class":541},"] ",[535,814,815],{"class":545},"!=",[535,817,818],{"class":545}," -",[535,820,683],{"class":549},[535,822,823],{"class":541},":\n",[535,825,826,829,832,835,837,839,841],{"class":537,"line":583},[535,827,828],{"class":545},"        return",[535,830,831],{"class":541}," liquid ",[535,833,834],{"class":545},">=",[535,836,805],{"class":541},[535,838,601],{"class":545},[535,840,604],{"class":549},[535,842,843],{"class":541},"]\n",[535,845,846,849,851],{"class":537,"line":610},[535,847,848],{"class":541},"    e ",[535,850,546],{"class":545},[535,852,853],{"class":541}," nodes.get(node)\n",[535,855,856,858],{"class":537,"line":634},[535,857,637],{"class":545},[535,859,860],{"class":541}," e:\n",[535,862,863,866,869,871,873,875,878,881,883],{"class":537,"line":655},[535,864,865],{"class":545},"        for",[535,867,868],{"class":541}," p ",[535,870,592],{"class":545},[535,872,595],{"class":549},[535,874,571],{"class":541},[535,876,877],{"class":549},"len",[535,879,880],{"class":541},"(e[",[535,882,672],{"class":549},[535,884,885],{"class":541},"])):\n",[535,887,888,891,893,895,898,901,903,906,909,912],{"class":537,"line":666},[535,889,890],{"class":541},"            down_pipe ",[535,892,546],{"class":545},[535,894,831],{"class":541},[535,896,897],{"class":545},"*",[535,899,900],{"class":541}," e[",[535,902,683],{"class":549},[535,904,905],{"class":541},"][p] ",[535,907,908],{"class":545},"\u002F",[535,910,911],{"class":549}," 100",[535,913,914],{"class":556},"  # e[1] это percentage — процентное значение для трубки\n",[535,916,917,920,922,924,927],{"class":537,"line":678},[535,918,919],{"class":545},"            if",[535,921,900],{"class":541},[535,923,694],{"class":549},[535,925,926],{"class":541},"][p]: ",[535,928,929],{"class":556},"# если \"супер трубка\"\n",[535,931,932,935,938,941],{"class":537,"line":689},[535,933,934],{"class":541},"                down_pipe ",[535,936,937],{"class":545},"*=",[535,939,940],{"class":541}," down_pipe  ",[535,942,943],{"class":556},"# 2\n",[535,945,946,948,951,954,956,959],{"class":537,"line":700},[535,947,919],{"class":545},[535,949,950],{"class":545}," not",[535,952,953],{"class":541}," can_feed(e[",[535,955,672],{"class":549},[535,957,958],{"class":541},"][p], down_pipe, nodes, liquid_needed): ",[535,960,961],{"class":556},"# 3\n",[535,963,964,967],{"class":537,"line":730},[535,965,966],{"class":545},"                return",[535,968,969],{"class":549}," False\n",[535,971,972,975],{"class":537,"line":742},[535,973,974],{"class":545},"    return",[535,976,977],{"class":549}," True\n",[426,979,980,981,984,985,987,988,990,991,993,994,996,997,999,1000,1002,1003,1006,1007,1010,1011,1013,1014,1017,1018,1020,1021,1024,1025,1028,1029,1031,1032,1034,1035,1038,1039,1041,1042,1045,1046,1049,1050,1052,1053,1056,1057,1060,1061,1063],{},"Функция отслеживает, является ли ",[532,982,983],{},"liquid"," допустимым решением для дерева.\nПока функция возвращает ",[532,986,776],{},", решение считается допустимым. По умолчанию функция вернёт ",[532,989,776],{}," а в процессе работы может вернуть ",[532,992,780],{},",\nесли количество жидкости, прошедшей через одну из трубок, окажется недостаточным. Если к концу работы функции по-прежнему будет\n",[532,995,776],{},", то все трубки провели достаточное количество жидкости и мы заключаем, что решение ",[532,998,983],{}," допустимо.\nКоличество жидкости, поступающее в каждую трубку, определяется с помощью ее процентного значения.\nЗатем, если трубка имеет супер режим, это значение возводится в квадрат... но стоп!\nВ условии задачи сказано, что Боби должен решить, нужно ли использовать супер режим каждой супер трубки.\nОднако здесь мы без вариантов возводим количество жидкости в квадрат, всегда используя супер режим.\nПричина в том, что возведение в квадрат увеличивает значения: сравните 2 и 2*2 = 4, 3 и 3*3 = 9, и т. д.\nПоскольку нам нужно знать, является ли данное количество жидкости допустимым, и штрафа за использование супер трубки нет,\nможно предполагать максимальный объем жидкости.\nВозможно, есть вариант обойтись и без использования супер режима какой-то супер трубки, но никто не просит нас экономить.\nНе беспокойтесь о том, что возведение в квадрат уменьшает положительные числа меньше единицы, например 0,5 (0,5 * 0,5 = 0,25).\nДействительно, в подобных случаях активировать супер трубку мы бы не стали. Поскольку каждому муравью нужно не менее 1 литра жидкости,\nзначит, если в одном из узлов мы получим 0,5 литра, то независимо от наших действий муравьи в поддереве этого узла останутся голодными и мы вернем ",[532,1001,780],{},".\nТеперь посмотрим, насколько полезна функция ",[532,1004,1005],{},"can_feed",", и для этого продолжим работу.\nРанее выше мы показали, что 10 литров недостаточно для рассматривавшегося примера.\nДобавьте вызов can_feed для проверки объема 10 литров(после получения тестовых данных): ",[532,1008,1009],{},"print(can_feed(1, 10, nodes, liquid_needed)",".\nВ результате должен вернуться ",[532,1012,780],{},", означающий, что ",[532,1015,1016],{},"10"," литров мало. В том же разделе мы продемонстрировали, что 20 литров будет достаточно.\nИзмените вызов ",[532,1019,1005],{}," для проверки ",[532,1022,1023],{},"20"," литров: ",[532,1026,1027],{},"print(can_feed(1, 20, nodes, liquid_needed)",".\nВ результате должна вернуться ",[532,1030,776],{},", означающая, что ",[532,1033,1023],{}," литров достаточно.\nТеперь нам известно, что 10 недостаточно, а 20 хватает. Давайте сужать этот диапазон далее.\nПопробуйте ",[532,1036,1037],{},"15",", на что должен вернуться ",[532,1040,780],{},". Значит, 15 маловато. Теперь оптимальный ответ больше 15, но не больше 20.\nПопробуйте ",[532,1043,1044],{},"18"," — в этом случае жидкости окажется достаточно. А как насчет ",[532,1047,1048],{},"17","?\nНет, ",[532,1051,1048],{}," уже мало, как и ",[532,1054,1055],{},"17.5"," или ",[532,1058,1059],{},"17.9",", значит, оптимальное решение — ",[532,1062,1044],{},".\nЭтих результатов узконаправленного поиска достаточно, теперь можно их систематизировать.",[520,1065,1067],{"id":1066},"поиск-решения","ПОИСК РЕШЕНИЯ",[426,1069,1070,1071],{},"Из условия задачи известно, что оптимальное значение не больше 2 миллиардов.\nСледовательно, решение находится в огромном пространстве поиска.\nНаша цель сократить это пространство максимально быстро, не тратя времени на пустые догадки.\nПромахнуться легко. Например, если начать с предположения 10, а оптимальное решение окажется равным двум миллиардам,\nтогда, по сути, это предположение следует считать промахом, исключающим из области поиска только значения от 0 до 10.\nНо 10 окажется отличным вариантом, если ответ будет равен, например, 8, потому что тогда первый же шаг сразу сократит диапазон до 0 — 10,\nи на поиск решения много времени не уйдет. Совершение таких выстрелов в небо себя не оправдывает,\nпоскольку редкое везение не перекроет наиболее вероятный случай, когда такая догадка практически бесполезна.\nИменно поэтому, когда вас попросят отгадать число между 0 и 1000, вы вряд ли начнете с 10.\nКонечно же, если на такое предположение вам скажут «меньше», то вы очень обрадуетесь, но если ответом будет «больше»,\nкак скорее всего и получится, то можно считать, что первую попытку вы потратили зря.\nЧтобы гарантировать получение с каждой догадкой максимальной информации, мы всегда будем загадывать середину диапазона.\nДля этого нужно будет вести две переменные, low и high, которые будут хранить нижнюю и верхнюю границы текущего диапазона соответственно.\nЗатем мы будем вычислять середину этого диапазона, mid, проверять допустимость mid, по результату обновляя low и high.\n",[406,1072,1073,1074,1078],{},"Используем алгоритм ",[1075,1076,1077],"em",{},"двоичного поиска",".",[525,1080,1082],{"className":527,"code":1081,"language":529,"meta":530,"style":530},"def solve(nodes, liquid_needed):\n    low = 0\n    high = 2000000000\n    while high - low > 0.00001: # 1\n        mid = (low + high) \u002F 2 # 2\n        if can_feed(1, mid, nodes, liquid_needed): # 3\n            high = mid\n        else:\n            low = mid\n    print(high) # 4\n",[532,1083,1084,1094,1104,1114,1139,1163,1178,1188,1195,1204],{"__ignoreMap":530},[535,1085,1086,1088,1091],{"class":537,"line":538},[535,1087,791],{"class":545},[535,1089,1090],{"class":794}," solve",[535,1092,1093],{"class":541},"(nodes, liquid_needed):\n",[535,1095,1096,1099,1101],{"class":537,"line":560},[535,1097,1098],{"class":541},"    low ",[535,1100,546],{"class":545},[535,1102,1103],{"class":549}," 0\n",[535,1105,1106,1109,1111],{"class":537,"line":583},[535,1107,1108],{"class":541},"    high ",[535,1110,546],{"class":545},[535,1112,1113],{"class":549}," 2000000000\n",[535,1115,1116,1119,1122,1124,1127,1130,1133,1136],{"class":537,"line":610},[535,1117,1118],{"class":545},"    while",[535,1120,1121],{"class":541}," high ",[535,1123,601],{"class":545},[535,1125,1126],{"class":541}," low ",[535,1128,1129],{"class":545},">",[535,1131,1132],{"class":549}," 0.00001",[535,1134,1135],{"class":541},": ",[535,1137,1138],{"class":556},"# 1\n",[535,1140,1141,1144,1146,1149,1152,1155,1157,1160],{"class":537,"line":634},[535,1142,1143],{"class":541},"        mid ",[535,1145,546],{"class":545},[535,1147,1148],{"class":541}," (low ",[535,1150,1151],{"class":545},"+",[535,1153,1154],{"class":541}," high) ",[535,1156,908],{"class":545},[535,1158,1159],{"class":549}," 2",[535,1161,1162],{"class":556}," # 2\n",[535,1164,1165,1168,1171,1173,1176],{"class":537,"line":655},[535,1166,1167],{"class":545},"        if",[535,1169,1170],{"class":541}," can_feed(",[535,1172,683],{"class":549},[535,1174,1175],{"class":541},", mid, nodes, liquid_needed): ",[535,1177,961],{"class":556},[535,1179,1180,1183,1185],{"class":537,"line":666},[535,1181,1182],{"class":541},"            high ",[535,1184,546],{"class":545},[535,1186,1187],{"class":541}," mid\n",[535,1189,1190,1193],{"class":537,"line":678},[535,1191,1192],{"class":545},"        else",[535,1194,823],{"class":541},[535,1196,1197,1200,1202],{"class":537,"line":689},[535,1198,1199],{"class":541},"            low ",[535,1201,546],{"class":545},[535,1203,1187],{"class":541},[535,1205,1206,1209,1212],{"class":537,"line":700},[535,1207,1208],{"class":549},"    print",[535,1210,1211],{"class":541},"(high) ",[535,1213,1214],{"class":556},"# 4\n",[426,1216,1217,1218,1221,1222,1225,1226,1229,1230,1232,1233,1235,1236,1238,1239,1241,1242,1244,1245,1248],{},"После определения функций и получения данных запустим решение: ",[532,1219,1220],{},"solve(nodes, liquid_needed)",".\nВажно инициализировать ",[532,1223,1224],{},"low"," и ",[532,1227,1228],{},"high"," так, чтобы в их диапазоне гарантированно содержалось оптимальное решение.\nЗначение ",[532,1231,1224],{}," будет постоянно меньшим или равным оптимальному решению, а ",[532,1234,1228],{}," — большим или равным оптимальному решению.\nНачнем со значения ",[532,1237,1224],{},", равного ",[532,1240,672],{},". Поскольку каждому муравью требуется не менее 1 литра, 0 литров будет определенно меньше или равно оптимальному решению.\nДля ",[532,1243,1228],{}," же стартовое значение установим как ",[532,1246,1247],{},"2000000000",", поскольку условие задачи гарантирует, что значение оптимального решения не может превышать этого числа.",[1250,1251,1252,1263,1274,1305],"ol",{},[462,1253,1254,1255,1225,1257,1259,1260,1078],{},"Условие цикла while ведет к минимизации диапазона между ",[532,1256,1224],{},[532,1258,1228],{},".\nНам нужна точность выше четырех цифр после запятой, отсюда появляются четыре 0 после десятичной точки в ",[532,1261,1262],{},"0.00001",[462,1264,1265,1266,1225,1268,1270,1271,1078],{},"Первым делом в цикле вычисляется середина диапазона. Для этого мы берем среднее от ",[532,1267,1224],{},[532,1269,1228],{},", сохраняя результат в ",[532,1272,1273],{},"mid",[462,1275,1276,1277,1279,1280,1282,1283,1285,1286,1288,1289,1292,1293,1295,1296,1298,1299,1302,1303,1078],{},"Теперь пора проверить ",[532,1278,1273],{}," литров на допустимость с помощью ",[532,1281,1005],{},". Если ",[532,1284,1273],{}," окажется допустимым числом, значит, угадывание значений выше ",[532,1287,1273],{}," бесполезно.\nСледовательно, мы устанавливаем ",[532,1290,1291],{},"high = mid",", уменьшая максимум диапазона до ",[532,1294,1273],{},". Если же ",[532,1297,1273],{}," окажется недопустимым вариантом, то бесполезно угадывать меньшие значения.\nСледовательно, мы устанавливаем ",[532,1300,1301],{},"low = mid",", повышая минимум диапазона до ",[532,1304,1273],{},[462,1306,1307,1308,1225,1310,1312,1313,1315,1316,1318],{},"По завершении цикла ",[532,1309,1224],{},[532,1311,1228],{}," окажутся очень близки. Я вывожу в конце ",[532,1314,1228],{},", но вывод ",[532,1317,1224],{}," также вполне допустим.",[426,1320,1321],{},"Такая техника, в которой мы последовательно сокращаем диапазон поиска в два раза, пока он не станет очень мал, называется двоичным поиском.\nЭто удивительно мощный алгоритм, что будет доказано в оставшихся разделах этой главы.\nОн также очень быстр и способен с легкостью обрабатывать диапазоны из миллиардов и триллионов значений.",[426,1323,1324],{},"«Кормление муравьев» относится к типу задач, для решения которых нет метода лучше двоичного поиска.\nДля них характерны две особенности:",[459,1326,1327,1333,1339],{},[462,1328,1329,1332],{},[406,1330,1331],{},"Особенность 1: сложность выбора метода решения, но простота проверки допустимости ответа.","\nДля некоторых задач сложно определить алгоритм поиска оптимального решения.\nК счастью, во многих таких случаях значительно проще определять, является ли предлагаемое решение допустимым.\nТакова и была ситуация в задаче про муравьев: мы не знали, как найти оптимальное решение, но при этом видели, как определять,\nявляется ли некоторый объем жидкости допустимым.",[462,1334,1335,1338],{},[406,1336,1337],{},"Особенность 2: четкое разделение решений на допустимые и недопустимые.","\nНам нужно, чтобы задача позволяла провести четкую черту, разделяющую допустимые и недопустимые решения.\nВ задаче про муравьев недостаточные объемы жидкости были недопустимы, а избыточные — допустимы.\nТо есть когда мы рассматривали значения объема, то могли установить для них диапазоны недопустимых и допустимых значений.\nПосле нахождения первого допустимого значения мы определяли диапазон, не содержащий недопустимых значений.\nПредположим, что выполняем проверку для 20 литров и выясняем, что этого мало.\nСледовательно, мы все еще не достигли допустимой части пространства поиска и нужно пробовать большие значения.\nЕсли же 20 литров оказывается достаточным, значит, мы находимся в допустимой части пространства и нужно пробовать меньшие значения.",[462,1340,1341],{},"Если задача не отвечает второму требованию, то двоичный поиск будет бесполезен.\nНапример, есть задачи, где меньшие значения являются недопустимыми, средние допустимыми, а большие снова недопустимыми.\nОднако вполне нормально, если область поиска будет переходить от допустимых значений к недопустимым, а не наоборот.",[520,1343,1345],{"id":1344},"время-выполнения-алгоритма","ВРЕМЯ ВЫПОЛНЕНИЯ АЛГОРИТМА",[426,1347,1348],{},"Пора окончательно разобраться, как мы использовали в задаче двоичный поиск: мы выполняли больше чем lb 2 000 000 000 итераций алгоритма, потому что\nне останавливались, когда ширина диапазона достигала 1. Остановка происходила только при достижении точности выше четырех знаков после запятой.\nПри добавлении пяти нулей количество совершаемых итераций равно lb 200 000 000 000 000, который округляется до 48.\nВсего 48 итераций необходимо для получения решения с точностью выше четырех цифр после запятой из огромнейшего диапазона в триллионы значений!",[426,1350,1351,1352,1355,1356,1358,1359,1362],{},"В дереве из ",[532,1353,1354],{},"N"," узлов функция ",[532,1357,1005],{}," в задаче «Кормление муравьев» выполняется в линейном времени, то есть продолжительность ее выполнения пропорциональна n.\nМы вызываем эту функцию lb(m × 104) раз, где m — ширина диапазона (два миллиарда в тестовых примерах).\nЭто пропорционально lbm работы. Тогда в общей сложности выполняется n работы lbm раз.\nТо есть время можно записать как ",[406,1360,1361],{},"O(nlbm)",". Оно не совсем линейно из-за множителя lbm, но двоичный поиск все равно очень быстр.",[426,1364,1365],{},[1075,1366,1367],{},[406,1368,1369],{},"ВЫВОД",[426,1371,1372],{},"В алгоритмах двоичного поиска мне больше всего нравится то, что для определения допустимости значения зачастую нужно использовать другой метод.\nТо есть снаружи у нас двоичный поиск, а внутри что-то еще, проверяющее каждое значение на допустимость.\nПричем это «что-то еще» может быть чем угодно.\nВ «Кормлении муравьев» это был поиск по дереву, в следующей задаче это может быть жадный алгоритм, а в третьей задаче главы и вовсе динамическое программирование.\nВ некоторых задачах для определения допустимости решения задействуется алгоритм на графах.",[426,1374,1375],{},"Таким образом, в задачах надо применять материал по другим алгоритмам.\nДля определения допустимости решений нередко требуется проявить изрядную креативность (к счастью, не столь изрядную, как для нахождения оптимальных решений).\nВерно, что двоичный поиск можно использовать для нахождения подходящего индекса массива в логарифмическом времени, но задачу про муравьев мы решали также с помощью двоичного поиска, а никакого массива задано не было.\nНе стоит ограничивать использование двоичного поиска только случаями, когда анализу подлежит массив. Этот алгоритм намного более гибок.",[410,1377,1379],{"id":1378},"задача-2-прыжки-вдоль-реки","Задача 2. Прыжки вдоль реки",[426,1381,1382],{},"Рассмотрим задачу, в которой для определения допустимости решений потребуется жадный алгоритм.",[402,1384,424],{"id":1385},"условие-1",[426,1387,1388],{},"Дана река длиной L, вдоль которой лежат камни. Один камень лежит в точке 0 (начало реки), другой в точке L (конец реки),\nа между ними находится еще n камней.\nНапример, вдоль реки длиной 12 камни могут располагаться в следующих местах: 0, 5, 8 и 12.\nКорова начинает с первого камня (локация 0), перепрыгивает оттуда на второй камень,\nпотом со второго на третий и так далее, пока не достигает последнего камня в точке L.\nМинимальная длина прыжка равна минимальному расстоянию между любыми двумя соседними камнями.\nВ примере выше минимальное расстояние будет 3 (между точками 5 и 8).\nФермеру Джону наскучили короткие прыжки коровы, и он хочет максимально\nувеличить их длину. Камни в точках 0 или L он убрать не может, но может удалить m других камней.\nПредположим, что в приведенном выше примере Джон может убрать один камень.\nВ этом случае перед ним стоит выбор — убрать камень из точки 5 или 6.\nЕсли он уберет его из точки 5, то минимальное расстояние прыжка станет 4 (из 8 в 12).\nОднако если он уберет камень из точки 8, то получит минимальный прыжок большей длины (из 0 в 5).\nЗадача — максимизация минимальной длины прыжка, которой может добиться фермер, убрав m камней.",[402,1390,454],{"id":1391},"входные-данные-1",[426,1393,1394],{},"Входные данные состоят из одного тестового примера, содержащего следующие строки:\nТри целых числа: L — протяженность реки; n — количество камней, не включая начальный и конечный камни;\nm — количество камней, которые Джон может убрать.\nЗначение L может находиться в диапазоне от 1 до 1 000 000 000, n — от 0 до 50 000, а m — между 0 и n.\nn строк, каждая из которых указывает координату камня. При этом два камня в одном месте оказаться не могут.",[402,1396,502],{"id":1397},"выходные-данные-1",[426,1399,1400],{},"Требуется вывести максимально достижимое минимальное расстояние прыжка.\nДля примера выше выводом будет 5.\nВремя на решение тестового примера — две секунды.",[402,1402,509],{"id":1403},"решение-1",[426,1405,1406],{},[1075,1407,1408],{},[406,1409,1410],{},"ЖАДНЫЙ АЛГОРИТМ",[426,1412,1413],{},"Сформулировать жадный алгоритм несложно, но не всегда легко определить правильное условие.\nЕсли он и подходят, то обычно по уникальным, характерным для конкретной задачи причинам. Эта задача одна из таких.\nОчень часто, чтобы отличить реально подходящий жадный алгоритм от кажущегося подходящим, требуется тщательное доказательство корректности.\nПример, алгоритм Дейкстры. Как правило, специалисты относят этот алгоритм именно к жадным.\nКогда он объявляет о нахождении кратчайшего пути к узлу, то уже не возвращается к этому решению.\nАлгоритм окончательно утверждает найденное значение, и дальнейшее исследование пространства поиска не влияет на этот результат.",[426,1415,1416],{},"Вот жадное правило для этой задачи: найти два камня, расположенных ближе всех друг к другу, убрать тот,\nчто ближе к другому своему соседу, и повторить процесс.\nВернемся к примеру из описания задачи:",[525,1418,1422],{"className":1419,"code":1420,"language":1421,"meta":530,"style":530},"language-markdown shiki shiki-themes github-light","12 2 1\n5\n8\n","markdown",[532,1423,1424,1429,1434],{"__ignoreMap":530},[535,1425,1426],{"class":537,"line":538},[535,1427,1428],{},"12 2 1\n",[535,1430,1431],{"class":537,"line":560},[535,1432,1433],{},"5\n",[535,1435,1436],{"class":537,"line":583},[535,1437,1438],{},"8\n",[426,1440,1441],{},"Камни расположены в точках 0, 5, 8 и 12. Убрать можно один.\nСамые близкие друг к другу камни расположены в 5 и 8, значит, жадное правило приведет к удалению одного из них.\nКамень в точке 8 находится от своего соседа справа на расстоянии 4.\nКамень в точке 5 находится от своего соседа слева на расстоянии 5.\nСогласно жадному правилу, удаляется камень из точки 8.\nВ этом примере правило работает корректно.",[426,1443,1444],{},"Но приведём контрпример:",[525,1446,1448],{"className":1419,"code":1447,"language":1421,"meta":530,"style":530},"12 4 2\n2\n4\n5\n8\n",[532,1449,1450,1455,1460,1465,1469],{"__ignoreMap":530},[535,1451,1452],{"class":537,"line":538},[535,1453,1454],{},"12 4 2\n",[535,1456,1457],{"class":537,"line":560},[535,1458,1459],{},"2\n",[535,1461,1462],{"class":537,"line":583},[535,1463,1464],{},"4\n",[535,1466,1467],{"class":537,"line":610},[535,1468,1433],{},[535,1470,1471],{"class":537,"line":634},[535,1472,1438],{},[426,1474,1475],{},"Камни располагаются в точках 0, 2, 4, 5, 8 и 12. Допускается убрать два.\nЖадный алгоритм определяет ближайшими камни в точках 4 и 5.\nИз них он удаляет камень 4, поскольку расстояние между 4 и 2 меньше, чем между 5 и 8. Остаются 0, 2, 5, 8 и 12.\nТеперь жадное правило определяет ближайшими камни в точках 0 и 2.\nУдалять стартовый камень нельзя, значит, удаляется камень из 2. Остаются 0, 5, 8 и 12. Минимальная длина прыжка здесь — 3.\nОднако в данном случае алгоритм с задачей не справился, потому что можно добиться, чтобы это расстояние равнялось 4.\nДля получения такого значения нужно удалить камни в точках 2 и 5. Так мы получим 0, 4, 8 и 12.",[426,1477,1478],{},"Что же пошло не так? Удалив камень в локации 4 на первом ходе, жадный алгоритм создал два прыжка с длиной три.\nНа втором ходе он может убрать только один из этих двух,\nчто никак не позволит получить итоговое минимальное расстояние больше трех.",[520,1480,1482],{"id":1481},"проверка-допустимости","ПРОВЕРКА ДОПУСТИМОСТИ",[426,1484,1485],{},"Всегда есть два ориентира используя двоичный поиск: большая простота проверки допустимости, чем определения оптимального решения;\nчеткий переход в области поиска между допустимыми и недопустимыми решениями.\nВместо поиска оптимального решения мы попробуем ответить на вопрос: можно ли добиться длины прыжка не менее d?\nЕсли нам удастся получить ответ, то можно будет использовать двоичный поиск для нахождения наибольшего допустимого значения d.\nТестовый пример на котором остановились:",[525,1487,1488],{"className":1419,"code":1447,"language":1421,"meta":530,"style":530},[532,1489,1490,1494,1498,1502,1506],{"__ignoreMap":530},[535,1491,1492],{"class":537,"line":538},[535,1493,1454],{},[535,1495,1496],{"class":537,"line":560},[535,1497,1459],{},[535,1499,1500],{"class":537,"line":583},[535,1501,1464],{},[535,1503,1504],{"class":537,"line":610},[535,1505,1433],{},[535,1507,1508],{"class":537,"line":634},[535,1509,1438],{},[426,1511,1512],{},"Камни расположены в точках 0, 2, 4, 5, 8 и 12. Убрать можно два. Вопрос: минимум сколько нужно убрать камней, чтобы длина прыжка получилась не менее 6?\nРазберем пример слева направо и проверим.",[426,1514,1515],{},"Камень в точке 0 трогать нельзя — так гласит условие задачи. Тогда, очевидно, у нас не остается выбора в отношении камня в точке 2: его необходимо убрать.\nЕсли этого не сделать, то минимальное расстояние между двумя камнями будет меньше 6.\nИтак, после этого остались камни в точках 0, 4, 5, 8 и 12. Теперь рассмотрим камень в точке 4 — нужно ли его оставить или убрать?\nВ нашем случае его необходимо также убрать.\nЕсли этого не сделать, то минимальное расстояние между камнями составит 4, что меньше нужных нам 6.\nПосле его удаления остаются камни в точках 0, 5, 8 и 12.\nКамень в точке 5 тоже надо убрать, потому что расстояние от него до 0 равно всего лишь 5.\nЭто третье удаление, после которого остаются камни в точках 0, 8 и 12.\nТеперь нужно удалить камень из точки 8. Он достаточно удален от 0, но недостаточно от 12.\nИтого четыре удаления, и в конечном итоге остаются камни в точках 0 и 12.",[426,1517,1518],{},"Итак, чтобы получить минимальное расстояние прыжка не меньше 6, требуется четыре удаления, но разрешено удалить всего два камня.\nВ таком случае 6 не является допустимым решением. Оно слишком велико. Будет ли допустимым решением 3?\nТо есть можно ли добиться минимального расстояния прыжка 3, удалив всего два камня?\nКамень в точке 0 остается, а камень в точке 2 нужно убрать.\nЭто первое удаление, оставляющее камни в позициях 0, 4, 5, 8 и 12. Камень в точке 4 может остаться: он удален от 0 более чем на 3.\nА вот камень в точке 5 нужно убрать, потому что он слишком близок к камню в точке 4.\nЭто второе удаление, после которого остаются заняты точки 0, 4, 8 и 12.\nКамень в точке 8 не мешает: он достаточно удален от камней в 4 и 12.\nЗначит, здесь мы закончили: для получения минимального расстояния прыжка 3 потребовалось два удаления.\nТаким образом, 3 является допустимым решением.",[426,1520,1521],{},"Здесь для проверки допустимости решения мы возвращаемся к жадному алгоритму.\nПравило получается следующее: поочередно рассматривать каждый камень и удалять его, если он оказывается слишком близок к предыдущему оставленному камню.\nДля предпоследнего камня надо выполнить проверку также относительно его правого соседа.\nЗатем подсчитывается число удаленных камней.\nЭтот результат сообщит нам, является ли предложенное минимальное расстояние прыжка допустимым с учетом количества камней,\nкоторое разрешено удалить (уточню, что это формулировка жадного алгоритма для проверки допустимости заданного расстояния прыжка,\nа не поиска оптимального решения). Реализация этого алгоритма представлена ниже:",[525,1523,1525],{"className":527,"code":1524,"language":529,"meta":530,"style":530},"def can_make_min_distance(distance, rocks, num_rocks, num_remove, length):\n  removed = prev_rock_location = 0\n  if length \u003C distance:\n    return False\n  for i in range(num_rocks):\n    cur_rock_location = rocks[i]\n    if cur_rock_location - prev_rock_location \u003C distance:\n      removed += 1\n    else:\n      prev_rock_location = cur_rock_location\n  if length - prev_rock_location \u003C distance:\n    removed += 1\n  return removed \u003C= num_remove\n",[532,1526,1527,1537,1551,1565,1571,1585,1595,1610,1621,1628,1638,1652,1661],{"__ignoreMap":530},[535,1528,1529,1531,1534],{"class":537,"line":538},[535,1530,791],{"class":545},[535,1532,1533],{"class":794}," can_make_min_distance",[535,1535,1536],{"class":541},"(distance, rocks, num_rocks, num_remove, length):\n",[535,1538,1539,1542,1544,1547,1549],{"class":537,"line":560},[535,1540,1541],{"class":541},"  removed ",[535,1543,546],{"class":545},[535,1545,1546],{"class":541}," prev_rock_location ",[535,1548,546],{"class":545},[535,1550,1103],{"class":549},[535,1552,1553,1556,1559,1562],{"class":537,"line":583},[535,1554,1555],{"class":545},"  if",[535,1557,1558],{"class":541}," length ",[535,1560,1561],{"class":545},"\u003C",[535,1563,1564],{"class":541}," distance:\n",[535,1566,1567,1569],{"class":537,"line":610},[535,1568,974],{"class":545},[535,1570,969],{"class":549},[535,1572,1573,1576,1578,1580,1582],{"class":537,"line":634},[535,1574,1575],{"class":545},"  for",[535,1577,589],{"class":541},[535,1579,592],{"class":545},[535,1581,595],{"class":549},[535,1583,1584],{"class":541},"(num_rocks):\n",[535,1586,1587,1590,1592],{"class":537,"line":655},[535,1588,1589],{"class":541},"    cur_rock_location ",[535,1591,546],{"class":545},[535,1593,1594],{"class":541}," rocks[i]\n",[535,1596,1597,1599,1602,1604,1606,1608],{"class":537,"line":666},[535,1598,637],{"class":545},[535,1600,1601],{"class":541}," cur_rock_location ",[535,1603,601],{"class":545},[535,1605,1546],{"class":541},[535,1607,1561],{"class":545},[535,1609,1564],{"class":541},[535,1611,1612,1615,1618],{"class":537,"line":678},[535,1613,1614],{"class":541},"      removed ",[535,1616,1617],{"class":545},"+=",[535,1619,1620],{"class":549}," 1\n",[535,1622,1623,1626],{"class":537,"line":689},[535,1624,1625],{"class":545},"    else",[535,1627,823],{"class":541},[535,1629,1630,1633,1635],{"class":537,"line":700},[535,1631,1632],{"class":541},"      prev_rock_location ",[535,1634,546],{"class":545},[535,1636,1637],{"class":541}," cur_rock_location\n",[535,1639,1640,1642,1644,1646,1648,1650],{"class":537,"line":730},[535,1641,1555],{"class":545},[535,1643,1558],{"class":541},[535,1645,601],{"class":545},[535,1647,1546],{"class":541},[535,1649,1561],{"class":545},[535,1651,1564],{"class":541},[535,1653,1654,1657,1659],{"class":537,"line":742},[535,1655,1656],{"class":541},"    removed ",[535,1658,1617],{"class":545},[535,1660,1620],{"class":549},[535,1662,1664,1667,1670,1673],{"class":537,"line":1663},13,[535,1665,1666],{"class":545},"  return",[535,1668,1669],{"class":541}," removed ",[535,1671,1672],{"class":545},"\u003C=",[535,1674,1675],{"class":541}," num_remove\n",[426,1677,1678],{},"У этой функции пять параметров:",[459,1680,1681,1684,1687,1690,1693],{},[462,1682,1683],{},"distance — минимальное расстояние прыжка, которое проверяется;",[462,1685,1686],{},"rocks — массив, содержащий координату каждого камня, кроме расположенных в начале и конце реки;",[462,1688,1689],{},"num_rocks — количество камней в массиве rocks;",[462,1691,1692],{},"num_remove — количество камней, которые можно убрать;",[462,1694,1695],{},"length — длина реки.",[426,1697,1698],{},"Эта функция возвращает True, если distance оказывается допустимым решением, и False, если нет.\nПеременная prev_rock_location отслеживает координату последнего нетронутого камня.\nВнутри цикла for переменная cur_rock_location содержит координату камня, рассматриваемого в данный момент.\nДалее идет проверка, определяющая, нужно ли оставить или удалить текущий камень.\nЕсли он находится слишком близко к предыдущему, то мы его удаляем и увеличиваем количество удалений на один.\nВ противном случае текущий камень остается, и соответствующим образом обновляется prev_rock_location.\nПо завершении цикла мы получаем количество камней, которое нужно удалить. Хотя не совсем.\nЕщё нужно проверить, не находится ли предпоследний камень слишком близко к концу реки.\nЕсли да, то он удаляется (не беспокойтесь о возможном удалении камня в точке 0.\nЕсли действительно удалить все камни, то prev_rock_location окажется равным 0.\nОднако length – 0 \u003C distance не может быть верно.\nВ противном случае сработала бы инструкция if еще в начале функции).\nИтак, условие расстояния прыжка между камнями соблюдено, причем мы удалили заданное число камней.",[426,1700,1701],{},"Прежде чем продолжать, давайте выполним проверку на допустимость. Ниже представлен тест для примера:",[525,1703,1705],{"className":527,"code":1704,"language":529,"meta":530,"style":530},"rocks = [2, 4, 5, 8];\nprint(can_make_min_distance(6, rocks, 4, 2, 12))\n",[532,1706,1707,1741],{"__ignoreMap":530},[535,1708,1709,1712,1714,1717,1719,1721,1724,1726,1729,1731,1734,1737],{"class":537,"line":538},[535,1710,1711],{"class":541},"rocks ",[535,1713,546],{"class":545},[535,1715,1716],{"class":541}," [",[535,1718,694],{"class":549},[535,1720,626],{"class":541},[535,1722,1723],{"class":549},"4",[535,1725,626],{"class":541},[535,1727,1728],{"class":549},"5",[535,1730,626],{"class":541},[535,1732,1733],{"class":549},"8",[535,1735,1736],{"class":541},"]",[535,1738,1740],{"class":1739},"sB1qb",";\n",[535,1742,1743,1745,1748,1751,1754,1756,1758,1760,1762,1765],{"class":537,"line":560},[535,1744,733],{"class":549},[535,1746,1747],{"class":541},"(can_make_min_distance(",[535,1749,1750],{"class":549},"6",[535,1752,1753],{"class":541},", rocks, ",[535,1755,1723],{"class":549},[535,1757,626],{"class":541},[535,1759,694],{"class":549},[535,1761,626],{"class":541},[535,1763,1764],{"class":549},"12",[535,1766,1767],{"class":541},"))\n",[426,1769,1770],{},"Можно ли достичь минимальной длины прыжка в шесть единиц, удалив два камня?\nОтвет «нет», значит, в выводе должен отобразиться False(ложно).\nИзмените первый параметр с 6 на 3, и теперь вопрос ставится о возможности получения минимальной длины в три единицы.\nЗапустите программу, и на этот раз в выводе отобразится True (верно).\nПревосходно: теперь у нас есть способ проверки допустимости.\nВремя задействовать двоичный поиск для нахождения оптимального решения.",[520,1772,1067],{"id":1773},"поиск-решения-1",[426,1775,1776],{},"Для использования двоичного поиска мы адаптируем код из задачи 1 в «Кормлении муравьев» требовалось достичь точности выше четырех знаков после запятой.\nЗдесь же нам нужно оптимизировать количество камней, выражаемое целочисленным значением.\nТак что вычисления будут останавливаться при целых значениях high и low.",[525,1778,1780],{"className":527,"code":1779,"language":529,"meta":530,"style":530},"def solve(rocks, num_rocks, num_remove, length):\n  low = 0\n  high = length + 1\n  while high - low > 1:\n    mid = (low + high) \u002F\u002F 2\n    if can_make_min_distance(mid, rocks, num_rocks, num_remove, length):\n      low = mid\n    else:\n      high = mid\n  print(low)\n",[532,1781,1782,1791,1800,1813,1830,1849,1856,1865,1871,1880],{"__ignoreMap":530},[535,1783,1784,1786,1788],{"class":537,"line":538},[535,1785,791],{"class":545},[535,1787,1090],{"class":794},[535,1789,1790],{"class":541},"(rocks, num_rocks, num_remove, length):\n",[535,1792,1793,1796,1798],{"class":537,"line":560},[535,1794,1795],{"class":541},"  low ",[535,1797,546],{"class":545},[535,1799,1103],{"class":549},[535,1801,1802,1805,1807,1809,1811],{"class":537,"line":583},[535,1803,1804],{"class":541},"  high ",[535,1806,546],{"class":545},[535,1808,1558],{"class":541},[535,1810,1151],{"class":545},[535,1812,1620],{"class":549},[535,1814,1815,1818,1820,1822,1824,1826,1828],{"class":537,"line":610},[535,1816,1817],{"class":545},"  while",[535,1819,1121],{"class":541},[535,1821,601],{"class":545},[535,1823,1126],{"class":541},[535,1825,1129],{"class":545},[535,1827,604],{"class":549},[535,1829,823],{"class":541},[535,1831,1832,1835,1837,1839,1841,1843,1846],{"class":537,"line":634},[535,1833,1834],{"class":541},"    mid ",[535,1836,546],{"class":545},[535,1838,1148],{"class":541},[535,1840,1151],{"class":545},[535,1842,1154],{"class":541},[535,1844,1845],{"class":545},"\u002F\u002F",[535,1847,1848],{"class":549}," 2\n",[535,1850,1851,1853],{"class":537,"line":655},[535,1852,637],{"class":545},[535,1854,1855],{"class":541}," can_make_min_distance(mid, rocks, num_rocks, num_remove, length):\n",[535,1857,1858,1861,1863],{"class":537,"line":666},[535,1859,1860],{"class":541},"      low ",[535,1862,546],{"class":545},[535,1864,1187],{"class":541},[535,1866,1867,1869],{"class":537,"line":678},[535,1868,1625],{"class":545},[535,1870,823],{"class":541},[535,1872,1873,1876,1878],{"class":537,"line":689},[535,1874,1875],{"class":541},"      high ",[535,1877,546],{"class":545},[535,1879,1187],{"class":541},[535,1881,1882,1885],{"class":537,"line":700},[535,1883,1884],{"class":549},"  print",[535,1886,1887],{"class":541},"(low)\n",[426,1889,1890],{},"Минимальное расстояние прыжка low, равное нулю, всегда достижимо и допустимо и high точно недопустимо: нельзя прыгнуть на длину length + 1.\nДалее нужно выяснить, что делать с этими двумя возможностями в цикле.\nВ каждой итерации мы вычисляем среднюю точку диапазона mid и используем вспомогательную функцию для проверки ее допустимости.\nЕсли mid окажется допустимо, то можно установить low = mid. Потому что low и все, что левее, является допустимым.\nЕсли же mid недопустимо, то можно установить high = mid. Потому что high и все правее него значения являются недопустимыми.\nТаким образом, в обоих случаях истинность инварианта сохраняется.\nМы видим, что никакой элемент кода не может повлиять на инвариант, а значит, можно спокойно наконец выводить low по завершении цикла.",[520,1892,523],{"id":1893},"считывание-входных-данных-1",[426,1895,1896],{},"Осталось только считать входные данные и вызвать solve:",[525,1898,1900],{"className":527,"code":1899,"language":529,"meta":530,"style":530},"rocks = []\nlength, num_rocks, num_remove = map(int, input().split())\nfor _ in range(num_rocks):\n  rocks.append(int(input()))\nrocks.sort()\nsolve(rocks, num_rocks, num_remove, length)\n",[532,1901,1902,1911,1930,1943,1957,1962],{"__ignoreMap":530},[535,1903,1904,1906,1908],{"class":537,"line":538},[535,1905,1711],{"class":541},[535,1907,546],{"class":545},[535,1909,1910],{"class":541}," []\n",[535,1912,1913,1916,1918,1920,1922,1924,1926,1928],{"class":537,"line":560},[535,1914,1915],{"class":541},"length, num_rocks, num_remove ",[535,1917,546],{"class":545},[535,1919,618],{"class":549},[535,1921,571],{"class":541},[535,1923,623],{"class":549},[535,1925,626],{"class":541},[535,1927,574],{"class":549},[535,1929,631],{"class":541},[535,1931,1932,1934,1937,1939,1941],{"class":537,"line":583},[535,1933,586],{"class":545},[535,1935,1936],{"class":541}," _ ",[535,1938,592],{"class":545},[535,1940,595],{"class":549},[535,1942,1584],{"class":541},[535,1944,1945,1948,1950,1952,1954],{"class":537,"line":610},[535,1946,1947],{"class":541},"  rocks.append(",[535,1949,623],{"class":549},[535,1951,571],{"class":541},[535,1953,574],{"class":549},[535,1955,1956],{"class":541},"()))\n",[535,1958,1959],{"class":537,"line":634},[535,1960,1961],{"class":541},"rocks.sort()\n",[535,1963,1964],{"class":537,"line":655},[535,1965,1966],{"class":541},"solve(rocks, num_rocks, num_remove, length)\n",[426,1968,1969,1970,1973],{},"Мы анализировали эту задачу, рассматривая координаты камней слева направо, то есть от наименьшего значения к наибольшему.\nОднако во входных данных они могут быть представлены в любом порядке, так как в условии задачи последовательность не гарантируется.\nПро алгоритмы сортировки нужно давать описание отдельно. Здесь же скажем что воспользуемся стандартным методом сортировки списков в Python ",[532,1971,1972],{},"sort()",".\nЗатем вызывается solve со списком упорядоченных камней.",[410,1975,1977],{"id":1976},"задача-3-качество-жизни","Задача 3. Качество жизни",[426,1979,1980],{},"Рассмотрим задачу, в которой для определения допустимости решений потребуется динамическое программирование.\nЭто задача из чемпионата мира по программированию (IOI 2010).",[402,1982,424],{"id":1983},"условие-2",[426,1985,1986,1987,1990,1991,1993,1994,1997,1998,2001,2002,2005],{},"Город состоит из прямоугольной сетки кварталов. Каждый квартал обозначается координатами строки и столбца.\nВсего есть ",[1075,1988,1989],{},"r"," строк, пронумерованных от 0 до ",[1075,1992,1989],{}," – 1 сверху вниз, и ",[1075,1995,1996],{},"c"," столбцов, пронумерованных от 0 до ",[1075,1999,2000],{},"с"," – 1 слева направо.\nКаждому квадрату присвоен индивидуальный ранг качества в диапазоне от 1 до ",[1075,2003,2004],{},"rc",".\nК примеру, если дано семь строк и семь столбцов, то рангами кварталов будут числа между 1 и 49.\nПример схемы города дан в таблице ниже.",[2007,2008,2009,2033],"table",{},[2010,2011,2012],"thead",{},[2013,2014,2015,2018,2020,2022,2024,2027,2029,2031],"tr",{},[2016,2017],"th",{},[2016,2019,672],{},[2016,2021,683],{},[2016,2023,694],{},[2016,2025,2026],{},"3",[2016,2028,1723],{},[2016,2030,1728],{},[2016,2032,1750],{},[2034,2035,2036,2062,2087,2112,2137,2163,2187],"tbody",{},[2013,2037,2038,2043,2046,2049,2051,2054,2057,2060],{},[2039,2040,2041],"td",{},[406,2042,672],{},[2039,2044,2045],{},"48",[2039,2047,2048],{},"16",[2039,2050,1037],{},[2039,2052,2053],{},"45",[2039,2055,2056],{},"40",[2039,2058,2059],{},"28",[2039,2061,1733],{},[2013,2063,2064,2068,2070,2073,2076,2079,2082,2084],{},[2039,2065,2066],{},[406,2067,683],{},[2039,2069,1023],{},[2039,2071,2072],{},"11",[2039,2074,2075],{},"36",[2039,2077,2078],{},"19",[2039,2080,2081],{},"24",[2039,2083,1750],{},[2039,2085,2086],{},"33",[2013,2088,2089,2093,2096,2099,2102,2105,2108,2110],{},[2039,2090,2091],{},[406,2092,694],{},[2039,2094,2095],{},"22",[2039,2097,2098],{},"39",[2039,2100,2101],{},"30",[2039,2103,2104],{},"7",[2039,2106,2107],{},"9",[2039,2109,683],{},[2039,2111,1044],{},[2013,2113,2114,2118,2121,2124,2126,2129,2132,2134],{},[2039,2115,2116],{},[406,2117,2026],{},[2039,2119,2120],{},"14",[2039,2122,2123],{},"35",[2039,2125,694],{},[2039,2127,2128],{},"13",[2039,2130,2131],{},"31",[2039,2133,1764],{},[2039,2135,2136],{},"46",[2013,2138,2139,2143,2146,2149,2152,2154,2157,2160],{},[2039,2140,2141],{},[406,2142,1723],{},[2039,2144,2145],{},"32",[2039,2147,2148],{},"37",[2039,2150,2151],{},"21",[2039,2153,2026],{},[2039,2155,2156],{},"41",[2039,2158,2159],{},"23",[2039,2161,2162],{},"29",[2013,2164,2165,2169,2172,2175,2178,2180,2182,2185],{},[2039,2166,2167],{},[406,2168,1728],{},[2039,2170,2171],{},"42",[2039,2173,2174],{},"49",[2039,2176,2177],{},"38",[2039,2179,1016],{},[2039,2181,1048],{},[2039,2183,2184],{},"47",[2039,2186,1728],{},[2013,2188,2189,2193,2196,2198,2201,2204,2207,2210],{},[2039,2190,2191],{},[406,2192,1750],{},[2039,2194,2195],{},"43",[2039,2197,1723],{},[2039,2199,2200],{},"34",[2039,2202,2203],{},"25",[2039,2205,2206],{},"26",[2039,2208,2209],{},"27",[2039,2211,2212],{},"44",[426,2214,2215,2218],{},[1075,2216,2217],{},"Средний ранг качества прямоугольника"," — это ранг качества, относительно которого другие ранги делятся на две равные половины — с меньшими и большими значениями.\nК примеру, рассмотрим прямоугольник размером пять строк на три столбца (5 × 3) в верхнем левом углу таблицы.\nОн содержит 15 рангов качества: 48, 16, 15, 20, 11, 36, 22, 39, 30, 14, 35, 2, 32, 37 и 21.\nСредним рангом здесь выступает 22, потому что семь чисел меньше 22, а другие семь — больше.",[426,2220,2221],{},"Нам будут даны целые числа h и w, указывающие высоту (количество строк) и ширину (количество столбцов) прямоугольников.\nЗадача — определить минимальный средний ранг качества любого прямоугольника с h строк и w столбцов.\nПредположим, что h равна 5, а w равна 3. Тогда для города в таблицы средним рангом качества будет определено значение 13.\nПрямоугольник со средним рангом качества 13 — этот тот, у которого верхний левый угол образует клетка (1, 3), а правый\nнижний угол — (5, 5).",[402,2223,454],{"id":2224},"входные-данные-2",[426,2226,2227],{},"Все необходимые данные необходимо подставить в параметры функции. Вот функция:",[525,2229,2231],{"className":527,"code":2230,"language":529,"meta":530,"style":530},"def rectangle(r, c, h, w, q):\n",[532,2232,2233],{"__ignoreMap":530},[535,2234,2235,2237,2240],{"class":537,"line":538},[535,2236,791],{"class":545},[535,2238,2239],{"class":794}," rectangle",[535,2241,2242],{"class":541},"(r, c, h, w, q):\n",[426,2244,2245,2246,1225,2248,2250,2251,1225,2254,2257,2258,2260,2261,2263,2264,2266,2267,2269,2270,1225,2272,2274,2275,2278,2279,2282,2283,2286],{},"Здесь ",[532,2247,1989],{},[532,2249,1996],{}," — количество строк и столбцов в схеме соответственно.\nАналогичным образом ",[532,2252,2253],{},"h",[532,2255,2256],{},"w"," — количество строк и столбцов в рассматриваемых прямоугольниках соответственно.\n",[532,2259,2253],{}," будет не больше ",[532,2262,1989],{},", а ",[532,2265,2256],{}," не больше ",[532,2268,1996],{},".\nТакже гарантируется, что ",[532,2271,2253],{},[532,2273,2256],{}," являются нечетными (произведение двух нечетных чисел — нечетное число, поэтому и ",[532,2276,2277],{},"hw",",\nколичество кварталов в рассматриваемом прямоугольнике, будет нечетным.\nСредний ранг качества в этом случае можно определить точно.\nЕсли же у нас будет четное количество рангов качества, например четыре ранга — 2, 6, 4 и 5, то среднее значение придется выбирать между 4 и 5.\nАвтор задачи избавил нас от этого выбора).\nЗаключительный параметр ",[532,2280,2281],{},"q"," указывает ранги качества кварталов.\nК примеру, ",[532,2284,2285],{},"q[2][3]"," определяет значение ранга квартала в строке 2, ряду 3.\nОбратите внимание, что максимальное количество и строк, и столбцов в городе — 3001.",[402,2288,502],{"id":2289},"выходные-данные-2",[426,2291,2292],{},"Вернуть минимальный средний ранг качества.\nВремя на решение тестового примера — 10 секунд.",[402,2294,509],{"id":2295},"решение-2",[426,2297,2298],{},[1075,2299,2300],{},[406,2301,2302],{},"УПОРЯДОЧИВАНИЕ ПРЯМОУГОЛЬНИКОВ",[426,2304,2305,2306,2308,2309,1078],{},"Во многом мы будем использовать двумерный массив ",[532,2307,2281],{},".\nПредположим, что даны координаты верхнего левого и правого нижнего углов прямоугольника и нужно определить средний ранг качества его кварталов.\nКак это сделать? Прежде чем ответить на этот вопрос создадим саму таблицу с данными(двумерный список) по нашему примеру и вызов функции ",[532,2310,2311],{},"rectangle",[525,2313,2315],{"className":527,"code":2314,"language":529,"meta":530,"style":530},"q = [[48, 16, 15, 45, 40, 28, 8], \n         [20, 11, 36, 19, 24, 6, 33], \n         [22, 39, 30, 7, 9, 1, 18], \n         [14, 35, 2, 13, 31, 12, 46], \n         [32, 37, 21, 3, 41, 23, 29], \n         [42, 49, 38, 10, 17, 47, 5], \n         [43, 4, 34, 25, 26, 27, 44]]\nresult = rectangle(7, 7, 5, 3, q)\nprint(result)\n",[532,2316,2317,2356,2389,2421,2453,2485,2517,2550,2577],{"__ignoreMap":530},[535,2318,2319,2322,2324,2327,2329,2331,2333,2335,2337,2339,2341,2343,2345,2347,2349,2351,2353],{"class":537,"line":538},[535,2320,2321],{"class":541},"q ",[535,2323,546],{"class":545},[535,2325,2326],{"class":541}," [[",[535,2328,2045],{"class":549},[535,2330,626],{"class":541},[535,2332,2048],{"class":549},[535,2334,626],{"class":541},[535,2336,1037],{"class":549},[535,2338,626],{"class":541},[535,2340,2053],{"class":549},[535,2342,626],{"class":541},[535,2344,2056],{"class":549},[535,2346,626],{"class":541},[535,2348,2059],{"class":549},[535,2350,626],{"class":541},[535,2352,1733],{"class":549},[535,2354,2355],{"class":541},"], \n",[535,2357,2358,2361,2363,2365,2367,2369,2371,2373,2375,2377,2379,2381,2383,2385,2387],{"class":537,"line":560},[535,2359,2360],{"class":541},"         [",[535,2362,1023],{"class":549},[535,2364,626],{"class":541},[535,2366,2072],{"class":549},[535,2368,626],{"class":541},[535,2370,2075],{"class":549},[535,2372,626],{"class":541},[535,2374,2078],{"class":549},[535,2376,626],{"class":541},[535,2378,2081],{"class":549},[535,2380,626],{"class":541},[535,2382,1750],{"class":549},[535,2384,626],{"class":541},[535,2386,2086],{"class":549},[535,2388,2355],{"class":541},[535,2390,2391,2393,2395,2397,2399,2401,2403,2405,2407,2409,2411,2413,2415,2417,2419],{"class":537,"line":583},[535,2392,2360],{"class":541},[535,2394,2095],{"class":549},[535,2396,626],{"class":541},[535,2398,2098],{"class":549},[535,2400,626],{"class":541},[535,2402,2101],{"class":549},[535,2404,626],{"class":541},[535,2406,2104],{"class":549},[535,2408,626],{"class":541},[535,2410,2107],{"class":549},[535,2412,626],{"class":541},[535,2414,683],{"class":549},[535,2416,626],{"class":541},[535,2418,1044],{"class":549},[535,2420,2355],{"class":541},[535,2422,2423,2425,2427,2429,2431,2433,2435,2437,2439,2441,2443,2445,2447,2449,2451],{"class":537,"line":610},[535,2424,2360],{"class":541},[535,2426,2120],{"class":549},[535,2428,626],{"class":541},[535,2430,2123],{"class":549},[535,2432,626],{"class":541},[535,2434,694],{"class":549},[535,2436,626],{"class":541},[535,2438,2128],{"class":549},[535,2440,626],{"class":541},[535,2442,2131],{"class":549},[535,2444,626],{"class":541},[535,2446,1764],{"class":549},[535,2448,626],{"class":541},[535,2450,2136],{"class":549},[535,2452,2355],{"class":541},[535,2454,2455,2457,2459,2461,2463,2465,2467,2469,2471,2473,2475,2477,2479,2481,2483],{"class":537,"line":634},[535,2456,2360],{"class":541},[535,2458,2145],{"class":549},[535,2460,626],{"class":541},[535,2462,2148],{"class":549},[535,2464,626],{"class":541},[535,2466,2151],{"class":549},[535,2468,626],{"class":541},[535,2470,2026],{"class":549},[535,2472,626],{"class":541},[535,2474,2156],{"class":549},[535,2476,626],{"class":541},[535,2478,2159],{"class":549},[535,2480,626],{"class":541},[535,2482,2162],{"class":549},[535,2484,2355],{"class":541},[535,2486,2487,2489,2491,2493,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513,2515],{"class":537,"line":655},[535,2488,2360],{"class":541},[535,2490,2171],{"class":549},[535,2492,626],{"class":541},[535,2494,2174],{"class":549},[535,2496,626],{"class":541},[535,2498,2177],{"class":549},[535,2500,626],{"class":541},[535,2502,1016],{"class":549},[535,2504,626],{"class":541},[535,2506,1048],{"class":549},[535,2508,626],{"class":541},[535,2510,2184],{"class":549},[535,2512,626],{"class":541},[535,2514,1728],{"class":549},[535,2516,2355],{"class":541},[535,2518,2519,2521,2523,2525,2527,2529,2531,2533,2535,2537,2539,2541,2543,2545,2547],{"class":537,"line":666},[535,2520,2360],{"class":541},[535,2522,2195],{"class":549},[535,2524,626],{"class":541},[535,2526,1723],{"class":549},[535,2528,626],{"class":541},[535,2530,2200],{"class":549},[535,2532,626],{"class":541},[535,2534,2203],{"class":549},[535,2536,626],{"class":541},[535,2538,2206],{"class":549},[535,2540,626],{"class":541},[535,2542,2209],{"class":549},[535,2544,626],{"class":541},[535,2546,2212],{"class":549},[535,2548,2549],{"class":541},"]]\n",[535,2551,2552,2555,2557,2560,2562,2564,2566,2568,2570,2572,2574],{"class":537,"line":678},[535,2553,2554],{"class":541},"result ",[535,2556,546],{"class":545},[535,2558,2559],{"class":541}," rectangle(",[535,2561,2104],{"class":549},[535,2563,626],{"class":541},[535,2565,2104],{"class":549},[535,2567,626],{"class":541},[535,2569,1728],{"class":549},[535,2571,626],{"class":541},[535,2573,2026],{"class":549},[535,2575,2576],{"class":541},", q)\n",[535,2578,2579,2581],{"class":537,"line":689},[535,2580,733],{"class":549},[535,2582,2583],{"class":541},"(result)\n",[426,2585,2586],{},[1075,2587,2588],{},[406,2589,2590],{},"Способ 1",[426,2592,2593],{},"Здесь поможет упорядочивание. Нужно просто отсортировать ранги качества от меньших к большим и затем выбрать элемент со средним индексом.\nРассмотрим, к примеру, все те же 15 рангов качества: 48, 16, 15, 20, 11, 36, 22, 39, 30, 14, 35, 2, 32, 37 и 21.\nЕсли их упорядочить, то получится: 2, 11, 14, 15, 16, 20, 21, 22, 30, 32, 35, 36, 37, 39 и 48.\nВсего здесь 15 рангов, значит, нужно взять восьмой (22), который и будет средним.\nЕсть и более быстрые алгоритмы для непосредственного нахождения среднего значения без необходимости упорядочивания.\nСортировка — алгоритм, которому для нахождения среднего значения требуется O(n logn) времени.\nСуществует и более сложный алгоритм для нахождения среднего со временем O(n). Но здесь мы не станем его использовать.\nРеализуемый в этом способе процесс будет настолько медленным, что никакое улучшение алгоритма поиска среднего значения\nвсе равно не поможет.",[426,2595,2596],{},"Итак, выше напишем функцию с кодом нахождения среднего в заданном прямоугольнике:",[525,2598,2600],{"className":527,"code":2599,"language":529,"meta":530,"style":530},"def median(top_row, left_col, bottom_row, right_col, q):\n        cur_rectangle = []\n        for i in range(top_row, bottom_row + 1):\n                for j in range(left_col, right_col + 1):\n                        cur_rectangle.append(q[i][j])\n        cur_rectangle.sort()\n        return cur_rectangle[len(cur_rectangle) \u002F\u002F 2]\n",[532,2601,2602,2612,2621,2640,2661,2666,2671],{"__ignoreMap":530},[535,2603,2604,2606,2609],{"class":537,"line":538},[535,2605,791],{"class":545},[535,2607,2608],{"class":794}," median",[535,2610,2611],{"class":541},"(top_row, left_col, bottom_row, right_col, q):\n",[535,2613,2614,2617,2619],{"class":537,"line":560},[535,2615,2616],{"class":541},"        cur_rectangle ",[535,2618,546],{"class":545},[535,2620,1910],{"class":541},[535,2622,2623,2625,2627,2629,2631,2634,2636,2638],{"class":537,"line":583},[535,2624,865],{"class":545},[535,2626,589],{"class":541},[535,2628,592],{"class":545},[535,2630,595],{"class":549},[535,2632,2633],{"class":541},"(top_row, bottom_row ",[535,2635,1151],{"class":545},[535,2637,604],{"class":549},[535,2639,607],{"class":541},[535,2641,2642,2645,2648,2650,2652,2655,2657,2659],{"class":537,"line":610},[535,2643,2644],{"class":545},"                for",[535,2646,2647],{"class":541}," j ",[535,2649,592],{"class":545},[535,2651,595],{"class":549},[535,2653,2654],{"class":541},"(left_col, right_col ",[535,2656,1151],{"class":545},[535,2658,604],{"class":549},[535,2660,607],{"class":541},[535,2662,2663],{"class":537,"line":634},[535,2664,2665],{"class":541},"                        cur_rectangle.append(q[i][j])\n",[535,2667,2668],{"class":537,"line":655},[535,2669,2670],{"class":541},"        cur_rectangle.sort()\n",[535,2672,2673,2675,2678,2680,2683,2685,2687],{"class":537,"line":666},[535,2674,828],{"class":545},[535,2676,2677],{"class":541}," cur_rectangle[",[535,2679,877],{"class":549},[535,2681,2682],{"class":541},"(cur_rectangle) ",[535,2684,1845],{"class":545},[535,2686,1159],{"class":549},[535,2688,843],{"class":541},[426,2690,2691,2692,2695,2696,2698,2699,2702,2703,2705,2706,2708],{},"Первые четыре параметра ",[532,2693,2694],{},"median"," очерчивают прямоугольник, указывая координаты его левого верхнего и правого нижнего углов.\nЗаключительный параметр ",[532,2697,2281],{}," содержит ранги качества. Для хранения рангов качества прямоугольника используется одномерный массив ",[532,2700,2701],{},"cur_rectangle",".\nВложенные циклы for проходят через каждую ячейку (квартал) прямоугольника и добавляют соответствующий ранг качества в ",[532,2704,2701],{},".\nПосле сбора всех рангов можно вызвать встроенный метод ",[532,2707,1972],{},".\nДалее нам будет в точности известно, где находится среднее значение — в середине массива, — и мы просто его возвращаем.\nВооружившись этой функцией, можно перебирать все варианты прямоугольника, и в конце определить тот, чей средний ранг качества окажется наименьшим.\nКод поиска наименьшего среднего значения среди возможных прямоугольников:",[525,2710,2712],{"className":527,"code":2711,"language":529,"meta":530,"style":530},"def rectangle(r, c, h, w, q):\n    best = r * c + 1\n    for top_row in range(r - h + 1):\n        for left_col in range(c - w + 1):\n            bottom_row = top_row + h - 1\n            right_col = left_col + w - 1\n            res = median(top_row, left_col, bottom_row, right_col, q)\n            if res \u003C best:\n                best = res\n    return best\n",[532,2713,2714,2722,2741,2767,2792,2809,2826,2836,2848,2858],{"__ignoreMap":530},[535,2715,2716,2718,2720],{"class":537,"line":538},[535,2717,791],{"class":545},[535,2719,2239],{"class":794},[535,2721,2242],{"class":541},[535,2723,2724,2727,2729,2732,2734,2737,2739],{"class":537,"line":560},[535,2725,2726],{"class":541},"    best ",[535,2728,546],{"class":545},[535,2730,2731],{"class":541}," r ",[535,2733,897],{"class":545},[535,2735,2736],{"class":541}," c ",[535,2738,1151],{"class":545},[535,2740,1620],{"class":549},[535,2742,2743,2746,2749,2751,2753,2756,2758,2761,2763,2765],{"class":537,"line":583},[535,2744,2745],{"class":545},"    for",[535,2747,2748],{"class":541}," top_row ",[535,2750,592],{"class":545},[535,2752,595],{"class":549},[535,2754,2755],{"class":541},"(r ",[535,2757,601],{"class":545},[535,2759,2760],{"class":541}," h ",[535,2762,1151],{"class":545},[535,2764,604],{"class":549},[535,2766,607],{"class":541},[535,2768,2769,2771,2774,2776,2778,2781,2783,2786,2788,2790],{"class":537,"line":610},[535,2770,865],{"class":545},[535,2772,2773],{"class":541}," left_col ",[535,2775,592],{"class":545},[535,2777,595],{"class":549},[535,2779,2780],{"class":541},"(c ",[535,2782,601],{"class":545},[535,2784,2785],{"class":541}," w ",[535,2787,1151],{"class":545},[535,2789,604],{"class":549},[535,2791,607],{"class":541},[535,2793,2794,2797,2799,2801,2803,2805,2807],{"class":537,"line":634},[535,2795,2796],{"class":541},"            bottom_row ",[535,2798,546],{"class":545},[535,2800,2748],{"class":541},[535,2802,1151],{"class":545},[535,2804,2760],{"class":541},[535,2806,601],{"class":545},[535,2808,1620],{"class":549},[535,2810,2811,2814,2816,2818,2820,2822,2824],{"class":537,"line":655},[535,2812,2813],{"class":541},"            right_col ",[535,2815,546],{"class":545},[535,2817,2773],{"class":541},[535,2819,1151],{"class":545},[535,2821,2785],{"class":541},[535,2823,601],{"class":545},[535,2825,1620],{"class":549},[535,2827,2828,2831,2833],{"class":537,"line":666},[535,2829,2830],{"class":541},"            res ",[535,2832,546],{"class":545},[535,2834,2835],{"class":541}," median(top_row, left_col, bottom_row, right_col, q)\n",[535,2837,2838,2840,2843,2845],{"class":537,"line":678},[535,2839,919],{"class":545},[535,2841,2842],{"class":541}," res ",[535,2844,1561],{"class":545},[535,2846,2847],{"class":541}," best:\n",[535,2849,2850,2853,2855],{"class":537,"line":689},[535,2851,2852],{"class":541},"                best ",[535,2854,546],{"class":545},[535,2856,2857],{"class":541}," res\n",[535,2859,2860,2862],{"class":537,"line":700},[535,2861,974],{"class":545},[535,2863,2864],{"class":541}," best\n",[426,2866,2867,2868,2871,2872,2875,2876,2879,2880,2882,2883,2885,2886,2888,2889,2891,2892,2894,2895,2897],{},"В переменной ",[532,2869,2870],{},"best"," сохраняется наилучшее (то есть наименьшее) среднее значение, найденное до сих пор.\nЭту переменную мы изначально устанавливаем с большим значением, которое превосходит среднее любого возможного прямоугольника.\nНевозможно, чтобы среднее прямоугольника равнялось ",[532,2873,2874],{},"r * с + 1",", это бы означало, что половина его рангов качества больше ",[532,2877,2878],{},"r * c",".\nНо, согласно условию задачи, никакие ранги качества не могут быть больше ",[532,2881,2878],{},".\nВложенные циклы ",[532,2884,586],{}," рассматривают все возможные координаты верхнего левого угла прямоугольника.\nТак мы получаем верхнюю строку и левый столбец, но для вызова ",[532,2887,2694],{}," нам также нужна нижняя строка и правый столбец.\nЧтобы вычислить координату нижней строки, мы берем номер верхней строки, прибавляем ",[532,2890,2253],{}," (количество строк в рассматриваемых прямоугольниках), а затем вычитаем ",[532,2893,683],{},".\nЗдесь очень просто допустить промах на единицу, но вычитание единицы необходимо.\nЕсли верхняя строка имеет номер 4, а h равна 2, то нам нужно, чтобы номер нижней строки был равен 4 + 2 – 1 = 5.\nЕсли же сделать этот номер равным 4 + 2 = 6, то у нас получится прямоугольник с тремя строками вместо требуемых двух.\nАналогичным образом вычисляется номер правого столбца.\nПолучив все четыре координаты, мы вызываем ",[532,2896,2694],{}," для вычисления среднего значения ранга прямоугольника.\nЕсли в итоге обнаруживается лучшее значение, то оставшаяся часть кода обновляет best.\nНа этом текущее решение закончено.",[426,2899,2900,2901,1225,2903,2905,2906,2909,2910,1225,2912,2914,2915,2918,2919,2921,2922,2924,2925,2928,2929,2931,2932,2935,2936,2938,2939,3183,3184,3286,3287,3289],{},"Но чтобы понять, почему наш код столь медленный, рассмотрим пример, в котором ",[532,2902,1989],{},[532,2904,2000],{}," представлены числом ",[1075,2907,2908],{},"m",".\nДля демонстрации наихудшего случая мы возьмем ",[532,2911,2253],{},[532,2913,2256],{},", равные ",[1075,2916,2917],{},"m\u002F2"," (нам не нужно, чтобы прямоугольники получались излишне большими, иначе их будет немного.\nНам также не нужно, чтобы они были слишком маленькими, так как тогда каждый будет легко обработать).\nСамая медленная часть функции ",[532,2920,2694],{}," — вызов ",[532,2923,1972],{},". Она получает массив с m\u002F2 × m\u002F2 = m*m\u002F4 значений.\nДля обработки массива из ",[1075,2926,2927],{},"n"," значений ",[532,2930,1972],{}," совершает ",[1075,2933,2934],{},"nlogn"," шагов.\nЗамена ",[1075,2937,2927],{}," на m*m\u002F4 дает оценку времени ",[2940,2941,2945],"mjx-container",{"className":2942,"jax":2944},[2943],"MathJax","SVG",[2946,2947,2955,3007],"svg",{"style":2948,"xmlns":2949,"width":2950,"height":2951,"role":441,"focusable":2952,"viewBox":2953,"xmlnsXLink":2954},"vertical-align: -0.566ex;","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","31.788ex","2.452ex","false","0 -833.9 14050.2 1083.9","http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxlink",[2956,2957,2958,2963,2967,2971,2975,2979,2983,2987,2991,2995,2999,3003],"defs",{},[2959,2960],"path",{"id":2961,"d":2962},"MJX-1-TEX-N-28","M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z",[2959,2964],{"id":2965,"d":2966},"MJX-1-TEX-I-1D45A","M21 287Q22 293 24 303T36 341T56 388T88 425T132 442T175 435T205 417T221 395T229 376L231 369Q231 367 232 367L243 378Q303 442 384 442Q401 442 415 440T441 433T460 423T475 411T485 398T493 385T497 373T500 364T502 357L510 367Q573 442 659 442Q713 442 746 415T780 336Q780 285 742 178T704 50Q705 36 709 31T724 26Q752 26 776 56T815 138Q818 149 821 151T837 153Q857 153 857 145Q857 144 853 130Q845 101 831 73T785 17T716 -10Q669 -10 648 17T627 73Q627 92 663 193T700 345Q700 404 656 404H651Q565 404 506 303L499 291L466 157Q433 26 428 16Q415 -11 385 -11Q372 -11 364 -4T353 8T350 18Q350 29 384 161L420 307Q423 322 423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 181Q151 335 151 342Q154 357 154 369Q154 405 129 405Q107 405 92 377T69 316T57 280Q55 278 41 278H27Q21 284 21 287Z",[2959,2968],{"id":2969,"d":2970},"MJX-1-TEX-N-32","M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z",[2959,2972],{"id":2973,"d":2974},"MJX-1-TEX-N-2F","M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z",[2959,2976],{"id":2977,"d":2978},"MJX-1-TEX-N-34","M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z",[2959,2980],{"id":2981,"d":2982},"MJX-1-TEX-N-29","M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z",[2959,2984],{"id":2985,"d":2986},"MJX-1-TEX-I-1D459","M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z",[2959,2988],{"id":2989,"d":2990},"MJX-1-TEX-I-1D45C","M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z",[2959,2992],{"id":2993,"d":2994},"MJX-1-TEX-I-1D454","M311 43Q296 30 267 15T206 0Q143 0 105 45T66 160Q66 265 143 353T314 442Q361 442 401 394L404 398Q406 401 409 404T418 412T431 419T447 422Q461 422 470 413T480 394Q480 379 423 152T363 -80Q345 -134 286 -169T151 -205Q10 -205 10 -137Q10 -111 28 -91T74 -71Q89 -71 102 -80T116 -111Q116 -121 114 -130T107 -144T99 -154T92 -162L90 -164H91Q101 -167 151 -167Q189 -167 211 -155Q234 -144 254 -122T282 -75Q288 -56 298 -13Q311 35 311 43ZM384 328L380 339Q377 350 375 354T369 368T359 382T346 393T328 402T306 405Q262 405 221 352Q191 313 171 233T151 117Q151 38 213 38Q269 38 323 108L331 118L384 328Z",[2959,2996],{"id":2997,"d":2998},"MJX-1-TEX-N-3D","M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z",[2959,3000],{"id":3001,"d":3002},"MJX-1-TEX-I-1D442","M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z",[2959,3004],{"id":3005,"d":3006},"MJX-1-TEX-N-2E","M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z",[3008,3009,3012],"g",{"stroke":3010,"fill":3010,"stroke-width":672,"transform":3011},"currentColor","scale(1,-1)",[3008,3013,3015,3022,3040,3051,3057,3063,3070,3077,3084,3089,3102,3109,3114,3119,3126,3133,3138,3151,3156,3161,3166,3171,3176],{"dataMmlNode":3014},"math",[3008,3016,3018],{"dataMmlNode":3017},"mo",[3019,3020],"use",{"dataC":2059,"xLinkHref":3021},"#MJX-1-TEX-N-28",[3008,3023,3026,3033],{"dataMmlNode":3024,"transform":3025},"msup","translate(389,0)",[3008,3027,3029],{"dataMmlNode":3028},"mi",[3019,3030],{"dataC":3031,"xLinkHref":3032},"1D45A","#MJX-1-TEX-I-1D45A",[3008,3034,3037],{"dataMmlNode":3035,"transform":3036},"mn","translate(911,363) scale(0.707)",[3019,3038],{"dataC":2145,"xLinkHref":3039},"#MJX-1-TEX-N-32",[3008,3041,3045],{"dataMmlNode":3042,"dataMjxTexclass":3043,"transform":3044},"TeXAtom","ORD","translate(1703.6,0)",[3008,3046,3047],{"dataMmlNode":3017},[3019,3048],{"dataC":3049,"xLinkHref":3050},"2F","#MJX-1-TEX-N-2F",[3008,3052,3054],{"dataMmlNode":3035,"transform":3053},"translate(2203.6,0)",[3019,3055],{"dataC":2200,"xLinkHref":3056},"#MJX-1-TEX-N-34",[3008,3058,3060],{"dataMmlNode":3017,"transform":3059},"translate(2703.6,0)",[3019,3061],{"dataC":2162,"xLinkHref":3062},"#MJX-1-TEX-N-29",[3008,3064,3066],{"dataMmlNode":3028,"transform":3065},"translate(3092.6,0)",[3019,3067],{"dataC":3068,"xLinkHref":3069},"1D459","#MJX-1-TEX-I-1D459",[3008,3071,3073],{"dataMmlNode":3028,"transform":3072},"translate(3390.6,0)",[3019,3074],{"dataC":3075,"xLinkHref":3076},"1D45C","#MJX-1-TEX-I-1D45C",[3008,3078,3080],{"dataMmlNode":3028,"transform":3079},"translate(3875.6,0)",[3019,3081],{"dataC":3082,"xLinkHref":3083},"1D454","#MJX-1-TEX-I-1D454",[3008,3085,3087],{"dataMmlNode":3017,"transform":3086},"translate(4352.6,0)",[3019,3088],{"dataC":2059,"xLinkHref":3021},[3008,3090,3092,3096],{"dataMmlNode":3024,"transform":3091},"translate(4741.6,0)",[3008,3093,3094],{"dataMmlNode":3028},[3019,3095],{"dataC":3031,"xLinkHref":3032},[3008,3097,3098],{"dataMmlNode":3042,"transform":3036,"dataMjxTexclass":3043},[3008,3099,3100],{"dataMmlNode":3035},[3019,3101],{"dataC":2145,"xLinkHref":3039},[3008,3103,3105],{"dataMmlNode":3042,"dataMjxTexclass":3043,"transform":3104},"translate(6056.1,0)",[3008,3106,3107],{"dataMmlNode":3017},[3019,3108],{"dataC":3049,"xLinkHref":3050},[3008,3110,3112],{"dataMmlNode":3035,"transform":3111},"translate(6556.1,0)",[3019,3113],{"dataC":2200,"xLinkHref":3056},[3008,3115,3117],{"dataMmlNode":3017,"transform":3116},"translate(7056.1,0)",[3019,3118],{"dataC":2162,"xLinkHref":3062},[3008,3120,3122],{"dataMmlNode":3017,"transform":3121},"translate(7722.9,0)",[3019,3123],{"dataC":3124,"xLinkHref":3125},"3D","#MJX-1-TEX-N-3D",[3008,3127,3129],{"dataMmlNode":3028,"transform":3128},"translate(8778.7,0)",[3019,3130],{"dataC":3131,"xLinkHref":3132},"1D442","#MJX-1-TEX-I-1D442",[3008,3134,3136],{"dataMmlNode":3017,"transform":3135},"translate(9541.7,0)",[3019,3137],{"dataC":2059,"xLinkHref":3021},[3008,3139,3141,3145],{"dataMmlNode":3024,"transform":3140},"translate(9930.7,0)",[3008,3142,3143],{"dataMmlNode":3028},[3019,3144],{"dataC":3031,"xLinkHref":3032},[3008,3146,3147],{"dataMmlNode":3042,"transform":3036,"dataMjxTexclass":3043},[3008,3148,3149],{"dataMmlNode":3035},[3019,3150],{"dataC":2145,"xLinkHref":3039},[3008,3152,3154],{"dataMmlNode":3028,"transform":3153},"translate(11245.2,0)",[3019,3155],{"dataC":3068,"xLinkHref":3069},[3008,3157,3159],{"dataMmlNode":3028,"transform":3158},"translate(11543.2,0)",[3019,3160],{"dataC":3075,"xLinkHref":3076},[3008,3162,3164],{"dataMmlNode":3028,"transform":3163},"translate(12028.2,0)",[3019,3165],{"dataC":3082,"xLinkHref":3083},[3008,3167,3169],{"dataMmlNode":3028,"transform":3168},"translate(12505.2,0)",[3019,3170],{"dataC":3031,"xLinkHref":3032},[3008,3172,3174],{"dataMmlNode":3017,"transform":3173},"translate(13383.2,0)",[3019,3175],{"dataC":2162,"xLinkHref":3062},[3008,3177,3179],{"dataMmlNode":3017,"transform":3178},"translate(13772.2,0)",[3019,3180],{"dataC":3181,"xLinkHref":3182},"2E","#MJX-1-TEX-N-2E","\nИтак, выполнение происходит уже медленнее, чем в квадратичном случае, — а мы ведь вычислили среднее значение только для одного прямоугольника.\nФункция rectangle вызывает median всего m*m\u002F4 раз, значит, общее время выполнения составляет ",[2940,3185,3187],{"className":3186,"jax":2944},[2943],[2946,3188,3192,3221],{"style":2948,"xmlns":2949,"width":3189,"height":3190,"role":441,"focusable":2952,"viewBox":3191,"xmlnsXLink":2954},"11.927ex","2.47ex","0 -841.7 5271.6 1091.7",[2956,3193,3194,3197,3200,3203,3206,3209,3212,3215,3218],{},[2959,3195],{"id":3196,"d":3002},"MJX-2-TEX-I-1D442",[2959,3198],{"id":3199,"d":2962},"MJX-2-TEX-N-28",[2959,3201],{"id":3202,"d":2966},"MJX-2-TEX-I-1D45A",[2959,3204],{"id":3205,"d":2978},"MJX-2-TEX-N-34",[2959,3207],{"id":3208,"d":2986},"MJX-2-TEX-I-1D459",[2959,3210],{"id":3211,"d":2990},"MJX-2-TEX-I-1D45C",[2959,3213],{"id":3214,"d":2994},"MJX-2-TEX-I-1D454",[2959,3216],{"id":3217,"d":2982},"MJX-2-TEX-N-29",[2959,3219],{"id":3220,"d":3006},"MJX-2-TEX-N-2E",[3008,3222,3223],{"stroke":3010,"fill":3010,"stroke-width":672,"transform":3011},[3008,3224,3225,3230,3236,3251,3257,3263,3269,3274,3280],{"dataMmlNode":3014},[3008,3226,3227],{"dataMmlNode":3028},[3019,3228],{"dataC":3131,"xLinkHref":3229},"#MJX-2-TEX-I-1D442",[3008,3231,3233],{"dataMmlNode":3017,"transform":3232},"translate(763,0)",[3019,3234],{"dataC":2059,"xLinkHref":3235},"#MJX-2-TEX-N-28",[3008,3237,3239,3244],{"dataMmlNode":3024,"transform":3238},"translate(1152,0)",[3008,3240,3241],{"dataMmlNode":3028},[3019,3242],{"dataC":3031,"xLinkHref":3243},"#MJX-2-TEX-I-1D45A",[3008,3245,3246],{"dataMmlNode":3042,"transform":3036,"dataMjxTexclass":3043},[3008,3247,3248],{"dataMmlNode":3035},[3019,3249],{"dataC":2200,"xLinkHref":3250},"#MJX-2-TEX-N-34",[3008,3252,3254],{"dataMmlNode":3028,"transform":3253},"translate(2466.6,0)",[3019,3255],{"dataC":3068,"xLinkHref":3256},"#MJX-2-TEX-I-1D459",[3008,3258,3260],{"dataMmlNode":3028,"transform":3259},"translate(2764.6,0)",[3019,3261],{"dataC":3075,"xLinkHref":3262},"#MJX-2-TEX-I-1D45C",[3008,3264,3266],{"dataMmlNode":3028,"transform":3265},"translate(3249.6,0)",[3019,3267],{"dataC":3082,"xLinkHref":3268},"#MJX-2-TEX-I-1D454",[3008,3270,3272],{"dataMmlNode":3028,"transform":3271},"translate(3726.6,0)",[3019,3273],{"dataC":3031,"xLinkHref":3243},[3008,3275,3277],{"dataMmlNode":3017,"transform":3276},"translate(4604.6,0)",[3019,3278],{"dataC":2162,"xLinkHref":3279},"#MJX-2-TEX-N-29",[3008,3281,3283],{"dataMmlNode":3017,"transform":3282},"translate(4993.6,0)",[3019,3284],{"dataC":3181,"xLinkHref":3285},"#MJX-2-TEX-N-2E","\nПри таком числе операций данное решение подходит только для примеров с очень малым количеством данных.\nВ нашем решении присутствуют два узких места.\nПервое — это упорядочивание каждого прямоугольника.\nВторое — это создание массива ",[532,3288,2701],{}," с нуля для каждого прямоугольника.\nИспользование двоичного поиска решает первую проблему, а динамическое программирование — вторую.",[520,3291,3293],{"id":3292},"двоичный-поиск","ДВОИЧНЫЙ ПОИСК",[426,3295,3296],{},"Почему нам стоит рассчитывать на то, что двоичный поиск обеспечит в данном случае прирост скорости?\nВо-первых, выше показано, что прямой поиск очень затратен. Подход, который опирался на сортировку, оказался медленнее m*m*m*m.\nВо-вторых, это еще один пример задачи, где сначала идут все недопустимые решения, а за ними уже допустимые.\nПредположим, что нет такого прямоугольника, чей средний ранг качества имеет значение менее 6.\nТогда не будет смысла искать прямоугольники со средним качеством 5, 4 или любым меньшим значением.\nИ наоборот, предположим, я скажу, что есть прямоугольник со средним рангом качества 5 или меньше.\nТеперь не будет смысла искать прямоугольники со средним рангом качества 6, 7 или любым другим, чье значение выше 5.\nТак задается область двоичного поиска.",[426,3298,3299,3300,3302,3303,3305,3306,3308],{},"В задаче с прыжками вдоль реки небольшие значения были допустимыми, а большие недопустимыми.\nЗдесь же у нас обратный случай: небольшие значения оказываются недопустимыми, а большие допустимыми.\nСледовательно, нам придется изменить инвариант, сменив расположение допустимых и недопустимых частей пространства решений.\nИ вот какой инвариант мы используем: ",[532,3301,1224],{}," и все, что меньше, будет недопустимо; ",[532,3304,1228],{}," и все, что больше, — допустимо.\nТаким образом, по завершении нужно возвращать ",[532,3307,1228],{},", поскольку таково будет наименьшее допустимое значение.",[525,3310,3312],{"className":527,"code":3311,"language":529,"meta":530,"style":530},"def rectangle(r, c, h, w, q):\n    low = 0\n    high = r * c + 1\n    while high - low > 1:\n        mid = (low + high) \u002F\u002F 2\n        if can_make_quality(mid, r, c, h, w, q):\n            high = mid\n        else:\n            low = mid\n    return high\n",[532,3313,3314,3322,3330,3346,3362,3378,3385,3393,3399,3407],{"__ignoreMap":530},[535,3315,3316,3318,3320],{"class":537,"line":538},[535,3317,791],{"class":545},[535,3319,2239],{"class":794},[535,3321,2242],{"class":541},[535,3323,3324,3326,3328],{"class":537,"line":560},[535,3325,1098],{"class":541},[535,3327,546],{"class":545},[535,3329,1103],{"class":549},[535,3331,3332,3334,3336,3338,3340,3342,3344],{"class":537,"line":583},[535,3333,1108],{"class":541},[535,3335,546],{"class":545},[535,3337,2731],{"class":541},[535,3339,897],{"class":545},[535,3341,2736],{"class":541},[535,3343,1151],{"class":545},[535,3345,1620],{"class":549},[535,3347,3348,3350,3352,3354,3356,3358,3360],{"class":537,"line":610},[535,3349,1118],{"class":545},[535,3351,1121],{"class":541},[535,3353,601],{"class":545},[535,3355,1126],{"class":541},[535,3357,1129],{"class":545},[535,3359,604],{"class":549},[535,3361,823],{"class":541},[535,3363,3364,3366,3368,3370,3372,3374,3376],{"class":537,"line":634},[535,3365,1143],{"class":541},[535,3367,546],{"class":545},[535,3369,1148],{"class":541},[535,3371,1151],{"class":545},[535,3373,1154],{"class":541},[535,3375,1845],{"class":545},[535,3377,1848],{"class":549},[535,3379,3380,3382],{"class":537,"line":655},[535,3381,1167],{"class":545},[535,3383,3384],{"class":541}," can_make_quality(mid, r, c, h, w, q):\n",[535,3386,3387,3389,3391],{"class":537,"line":666},[535,3388,1182],{"class":541},[535,3390,546],{"class":545},[535,3392,1187],{"class":541},[535,3394,3395,3397],{"class":537,"line":678},[535,3396,1192],{"class":545},[535,3398,823],{"class":541},[535,3400,3401,3403,3405],{"class":537,"line":689},[535,3402,1199],{"class":541},[535,3404,546],{"class":545},[535,3406,1187],{"class":541},[535,3408,3409,3411],{"class":537,"line":700},[535,3410,974],{"class":545},[535,3412,3413],{"class":541}," high\n",[426,3415,3416,3417,1078],{},"Для завершения нужно проверить допустимость с помощью ",[532,3418,3419],{},"can_make_quality",[520,3421,1482],{"id":3422},"проверка-допустимости-1",[426,3424,3425,3426,3429,3430,3433],{},"Вот функция проверки допустимости: ",[532,3427,3428],{},"def can_make_quality(quality, r, c, h, w, q):",".\nНам достаточно будет определять, не превосходит ли среднее значение некоторого прямоугольника пороговое значение ранга ",[532,3431,3432],{},"quality",".\nЭто более простая задача, для которой этап сортировки необязателен.\nКонкретные значения нам больше не важны, принципиально только соотношение между каждым значением и quality.\nПоэтому мы заменим все меньшие или равные quality значения на –1, а все большие — на 1.\nЗатем мы сложим эти –1 и 1 для заданного прямоугольника. Если в итоге значений –1 получится столько же или больше, чем значений 1\n(т.е. относительно quality число меньших значений будет превосходить количество больших),\nто их сумма будет нулевой или отрицательной и мы сделаем вывод, что средний ранг качества данного прямоугольника равен quality или меньше него.",[426,3435,3436],{},"Рассмотрим пример, в котором снова возьмем 15 рангов для прямоугольника 5 × 3 из верхнего левого угла таблицы условия:\n48, 16, 15, 20, 11, 36, 22, 39, 30, 14, 35, 2, 32, 37 и 21.\nСравним средний ранг качества этого прямоугольника с 16.\nДля этого возьмем каждое значение и, если оно меньше или равно 16, заменим его на –1, а если больше 16, то на 1.\nПолучатся следующие значения: 1, –1, –1, 1, –1, 1, 1, 1, 1, –1, 1, –1, 1, 1 и 1.\nИх сложение даст 5. Это означает, что значений, превосходящих 16, на пять больше, чем меньших или равных этому числу.\nЭто, в свою очередь, говорит о том, что среднее значение 16 или меньше для данного прямоугольника невозможно.\nЕсли бы мы хотели узнать, является ли допустимым среднее значение 30,\nто также узнали бы об этом, заменив числа на –1 и 1: 1, –1, –1, –1, –1, 1, –1, 1, –1, –1, 1, –1, 1, 1 и –1.\nСложение этих значений даст –3. Значит, 30 является допустимым средним.\nВажно отметить, что решение о допустимости\u002Fнедопустимости принимается без предварительного упорядочивания.\nНам нужно перебрать каждый прямоугольник, проверяя, содержит ли он средний ранг качества, равный quality или меньше него.\nЭтот процесс реализуется в коде ниже:",[525,3438,3440],{"className":527,"code":3439,"language":529,"meta":530,"style":530},"def can_make_quality(quality, r, c, h, w, q):\n    zero_one = [row[:] for row in q]\n    for i in range(r):\n        for j in range(c):\n            if q[i][j] \u003C= quality:\n                zero_one[i][j] = -1\n            else:\n                zero_one[i][j] = 1\n    for top_row in range(r - h + 1):\n        for left_col in range(c - w + 1):\n            bottom_row = top_row + h - 1\n            right_col = left_col + w - 1\n            total = 0\n            for i in range(top_row, bottom_row + 1):\n                for j in range(left_col, right_col + 1):\n                    total = total + zero_one[i][j]\n            if total \u003C= 0:\n                return True\n    return False\n",[532,3441,3442,3452,3472,3485,3498,3510,3522,3529,3537,3559,3581,3597,3613,3622,3642,3661,3677,3691,3698],{"__ignoreMap":530},[535,3443,3444,3446,3449],{"class":537,"line":538},[535,3445,791],{"class":545},[535,3447,3448],{"class":794}," can_make_quality",[535,3450,3451],{"class":541},"(quality, r, c, h, w, q):\n",[535,3453,3454,3457,3459,3462,3464,3467,3469],{"class":537,"line":560},[535,3455,3456],{"class":541},"    zero_one ",[535,3458,546],{"class":545},[535,3460,3461],{"class":541}," [row[:] ",[535,3463,586],{"class":545},[535,3465,3466],{"class":541}," row ",[535,3468,592],{"class":545},[535,3470,3471],{"class":541}," q]\n",[535,3473,3474,3476,3478,3480,3482],{"class":537,"line":583},[535,3475,2745],{"class":545},[535,3477,589],{"class":541},[535,3479,592],{"class":545},[535,3481,595],{"class":549},[535,3483,3484],{"class":541},"(r):\n",[535,3486,3487,3489,3491,3493,3495],{"class":537,"line":610},[535,3488,865],{"class":545},[535,3490,2647],{"class":541},[535,3492,592],{"class":545},[535,3494,595],{"class":549},[535,3496,3497],{"class":541},"(c):\n",[535,3499,3500,3502,3505,3507],{"class":537,"line":634},[535,3501,919],{"class":545},[535,3503,3504],{"class":541}," q[i][j] ",[535,3506,1672],{"class":545},[535,3508,3509],{"class":541}," quality:\n",[535,3511,3512,3515,3517,3519],{"class":537,"line":655},[535,3513,3514],{"class":541},"                zero_one[i][j] ",[535,3516,546],{"class":545},[535,3518,818],{"class":545},[535,3520,3521],{"class":549},"1\n",[535,3523,3524,3527],{"class":537,"line":666},[535,3525,3526],{"class":545},"            else",[535,3528,823],{"class":541},[535,3530,3531,3533,3535],{"class":537,"line":678},[535,3532,3514],{"class":541},[535,3534,546],{"class":545},[535,3536,1620],{"class":549},[535,3538,3539,3541,3543,3545,3547,3549,3551,3553,3555,3557],{"class":537,"line":689},[535,3540,2745],{"class":545},[535,3542,2748],{"class":541},[535,3544,592],{"class":545},[535,3546,595],{"class":549},[535,3548,2755],{"class":541},[535,3550,601],{"class":545},[535,3552,2760],{"class":541},[535,3554,1151],{"class":545},[535,3556,604],{"class":549},[535,3558,607],{"class":541},[535,3560,3561,3563,3565,3567,3569,3571,3573,3575,3577,3579],{"class":537,"line":700},[535,3562,865],{"class":545},[535,3564,2773],{"class":541},[535,3566,592],{"class":545},[535,3568,595],{"class":549},[535,3570,2780],{"class":541},[535,3572,601],{"class":545},[535,3574,2785],{"class":541},[535,3576,1151],{"class":545},[535,3578,604],{"class":549},[535,3580,607],{"class":541},[535,3582,3583,3585,3587,3589,3591,3593,3595],{"class":537,"line":730},[535,3584,2796],{"class":541},[535,3586,546],{"class":545},[535,3588,2748],{"class":541},[535,3590,1151],{"class":545},[535,3592,2760],{"class":541},[535,3594,601],{"class":545},[535,3596,1620],{"class":549},[535,3598,3599,3601,3603,3605,3607,3609,3611],{"class":537,"line":742},[535,3600,2813],{"class":541},[535,3602,546],{"class":545},[535,3604,2773],{"class":541},[535,3606,1151],{"class":545},[535,3608,2785],{"class":541},[535,3610,601],{"class":545},[535,3612,1620],{"class":549},[535,3614,3615,3618,3620],{"class":537,"line":1663},[535,3616,3617],{"class":541},"            total ",[535,3619,546],{"class":545},[535,3621,1103],{"class":549},[535,3623,3625,3628,3630,3632,3634,3636,3638,3640],{"class":537,"line":3624},14,[535,3626,3627],{"class":545},"            for",[535,3629,589],{"class":541},[535,3631,592],{"class":545},[535,3633,595],{"class":549},[535,3635,2633],{"class":541},[535,3637,1151],{"class":545},[535,3639,604],{"class":549},[535,3641,607],{"class":541},[535,3643,3645,3647,3649,3651,3653,3655,3657,3659],{"class":537,"line":3644},15,[535,3646,2644],{"class":545},[535,3648,2647],{"class":541},[535,3650,592],{"class":545},[535,3652,595],{"class":549},[535,3654,2654],{"class":541},[535,3656,1151],{"class":545},[535,3658,604],{"class":549},[535,3660,607],{"class":541},[535,3662,3664,3667,3669,3672,3674],{"class":537,"line":3663},16,[535,3665,3666],{"class":541},"                    total ",[535,3668,546],{"class":545},[535,3670,3671],{"class":541}," total ",[535,3673,1151],{"class":545},[535,3675,3676],{"class":541}," zero_one[i][j]\n",[535,3678,3680,3682,3684,3686,3689],{"class":537,"line":3679},17,[535,3681,919],{"class":545},[535,3683,3671],{"class":541},[535,3685,1672],{"class":545},[535,3687,3688],{"class":549}," 0",[535,3690,823],{"class":541},[535,3692,3694,3696],{"class":537,"line":3693},18,[535,3695,966],{"class":545},[535,3697,977],{"class":549},[535,3699,3701,3703],{"class":537,"line":3700},19,[535,3702,974],{"class":545},[535,3704,969],{"class":549},[426,3706,3707,3708,3711,3712,3714],{},"Нельзя просто заместить массив q значениями –1 и 1, потому что тогда мы не сможем использовать исходные ранги качества для последующей проверки других значений quality.\nСледовательно, здесь для хранения –1 и 1 создается новый массив ",[532,3709,3710],{},"zero_one",".\nОбратите внимание, что он заполняется на основании того, является ли каждое значение меньшим или равным (–1) либо большим (1), чем пороговый параметр ",[532,3713,3432],{},".\nДалее мы проходим по каждому прямоугольнику так же. При этом суммируются все его –1 и 1, и возвращается True (верно), если средний ранг качества оказывается достаточно мал.",[426,3716,3717,3718,3720],{},"Вот мы и избавились от сортировки — искусно, не так ли? Этот прием очень важен для решения нашей задачи, но недостаточен.\nЕсли посчитать вложенные циклы, то окажется, что у нас их целых четыре.\nМы обнаружили, что решение без двоичного поиска оказалось очень медленным.\nЗдесь же оценка скорости проверки допустимости все еще равна m",[1075,3719,2908],{},"m*m.\nУмножьте ее на логарифмический множитель, характеризующий двоичный поиск, и возникнет вопрос: а добились ли мы хоть какого-нибудь прогресса?\nНо мы добились! Просто он скрыт за слишком большим числом вложенных циклов, производящих чересчур много вычислений.\nОставшуюся часть пути нам поможет пройти динамическое программирование.",[520,3722,3724],{"id":3723},"ускоренная-проверка-допустимости","УСКОРЕННАЯ ПРОВЕРКА ДОПУСТИМОСТИ",[426,3726,3727],{},"Предположим, что дана таблица(как в условии задачи выше) и требуется выяснить, содержит ли какой-либо из прямоугольников 5 × 3 средний ранг качества 16 или менее.\nИзменив все значения, которые меньше или равны 16, на –1, а все значения больше 16 — на 1, получим следующую таблицу:",[2007,3729,3730,3750],{},[2010,3731,3732],{},[2013,3733,3734,3736,3738,3740,3742,3744,3746,3748],{},[2016,3735],{},[2016,3737,672],{},[2016,3739,683],{},[2016,3741,694],{},[2016,3743,2026],{},[2016,3745,1723],{},[2016,3747,1728],{},[2016,3749,1750],{},[2034,3751,3752,3773,3793,3813,3833,3853,3873],{},[2013,3753,3754,3758,3760,3763,3765,3767,3769,3771],{},[2039,3755,3756],{},[406,3757,672],{},[2039,3759,683],{},[2039,3761,3762],{},"-1",[2039,3764,3762],{},[2039,3766,683],{},[2039,3768,683],{},[2039,3770,683],{},[2039,3772,3762],{},[2013,3774,3775,3779,3781,3783,3785,3787,3789,3791],{},[2039,3776,3777],{},[406,3778,683],{},[2039,3780,683],{},[2039,3782,3762],{},[2039,3784,683],{},[2039,3786,683],{},[2039,3788,683],{},[2039,3790,3762],{},[2039,3792,683],{},[2013,3794,3795,3799,3801,3803,3805,3807,3809,3811],{},[2039,3796,3797],{},[406,3798,694],{},[2039,3800,683],{},[2039,3802,683],{},[2039,3804,683],{},[2039,3806,3762],{},[2039,3808,3762],{},[2039,3810,3762],{},[2039,3812,683],{},[2013,3814,3815,3819,3821,3823,3825,3827,3829,3831],{},[2039,3816,3817],{},[406,3818,2026],{},[2039,3820,3762],{},[2039,3822,683],{},[2039,3824,3762],{},[2039,3826,3762],{},[2039,3828,683],{},[2039,3830,3762],{},[2039,3832,683],{},[2013,3834,3835,3839,3841,3843,3845,3847,3849,3851],{},[2039,3836,3837],{},[406,3838,1723],{},[2039,3840,683],{},[2039,3842,683],{},[2039,3844,683],{},[2039,3846,3762],{},[2039,3848,683],{},[2039,3850,683],{},[2039,3852,683],{},[2013,3854,3855,3859,3861,3863,3865,3867,3869,3871],{},[2039,3856,3857],{},[406,3858,1728],{},[2039,3860,683],{},[2039,3862,683],{},[2039,3864,683],{},[2039,3866,3762],{},[2039,3868,683],{},[2039,3870,683],{},[2039,3872,3762],{},[2013,3874,3875,3879,3881,3883,3885,3887,3889,3891],{},[2039,3876,3877],{},[406,3878,1750],{},[2039,3880,683],{},[2039,3882,3762],{},[2039,3884,683],{},[2039,3886,683],{},[2039,3888,683],{},[2039,3890,683],{},[2039,3892,683],{},[426,3894,3895],{},"Можно начать с суммирования элементов прямоугольника 5 × 3 с координатами верхнего левого угла (0, 0).\nСумма значений этого прямоугольника равна 5. Далее вычислим сумму элементов прямоугольника 5 × 3 с координатами верхнего левого угла (0, 1).\nРанее мы бы в данном случае сложили все 15 чисел. Однако тогда мы не сможем воспользоваться результатами вычислений суммы первого прямоугольника.\nДействительно, во втором прямоугольнике есть 10 общих значений с первым.\nНам нужно избежать подобного дублирования работы как для этого, так и для всех остальных прямоугольников.\nИсключение повторения работы здесь подразумевает эффективное выполнение так называемого запроса суммы двумерного диапазона.\nОдномерный случай реализуется по тем же принципам, но проще, поэтому сперва мы вкратце изучим его, а потом уже вернемся к завершению задачи.",[426,3897,3898],{},[1075,3899,3900],{},[406,3901,3902],{},"Запрос суммы одномерного диапазона",[426,3904,3905],{},"Рассмотрим одномерный массив:",[2007,3907,3908,3929],{},[2010,3909,3910],{},[2013,3911,3912,3915,3917,3919,3921,3923,3925,3927],{},[2016,3913,3914],{},"Индекс",[2016,3916,672],{},[2016,3918,683],{},[2016,3920,694],{},[2016,3922,2026],{},[2016,3924,1723],{},[2016,3926,1728],{},[2016,3928,1750],{},[2034,3930,3931],{},[2013,3932,3933,3938,3940,3942,3944,3946,3948,3950],{},[2039,3934,3935],{},[406,3936,3937],{},"Значение",[2039,3939,1750],{},[2039,3941,694],{},[2039,3943,1037],{},[2039,3945,2107],{},[2039,3947,1764],{},[2039,3949,1723],{},[2039,3951,2072],{},[426,3953,3954],{},"Если требуется найти сумму элементов массива от индекса 2 до индекса 5, то можно напрямую суммировать значения в этом диапазоне: 15 + 9 + 12 + 4 = 40.\nЭто не очень быстро, и будет совсем печально, если потребуется найти сумму всего массива.\nОднако если требуется ответить всего на несколько таких запросов, то этот вариант приемлем, и можно каждый раз суммировать соответствующие значения.\nТеперь представим, что мы получаем сотни или даже тысячи подобных запросов.\nТогда есть смысл единожды проделать предварительную работу, которая позволит отвечать на них быстрее.\nРассмотрим запрос от индекса 2 до 5. Что, если предварительно найти сумму значений от индекса 0 до 5? Она равна 48.\nЭто не нужный нам ответ, которым является 40, однако здесь удобен тот факт, что 48 находится от него недалеко.\nОшибочно это значение лишь потому, что включает индексы 0 и 1, которые теперь нужно исключить.\nЭто можно быстро сделать при условии нахождения их суммы, которая равна 8. Если вычесть 8 из 48, то получится нужная сумма 40.\nВ таком случае нам нужен новый массив, тот, где индекс i содержит сумму всех значений от индекса 0 до i.\nЭтот новый массив добавляется в строку частичной суммы в следующей таблице:",[2007,3956,3957,3977],{},[2010,3958,3959],{},[2013,3960,3961,3963,3965,3967,3969,3971,3973,3975],{},[2016,3962,3914],{},[2016,3964,672],{},[2016,3966,683],{},[2016,3968,694],{},[2016,3970,2026],{},[2016,3972,1723],{},[2016,3974,1728],{},[2016,3976,1750],{},[2034,3978,3979,3999],{},[2013,3980,3981,3985,3987,3989,3991,3993,3995,3997],{},[2039,3982,3983],{},[406,3984,3937],{},[2039,3986,1750],{},[2039,3988,694],{},[2039,3990,1037],{},[2039,3992,2107],{},[2039,3994,1764],{},[2039,3996,1723],{},[2039,3998,2072],{},[2013,4000,4001,4006,4008,4010,4012,4014,4016,4018],{},[2039,4002,4003],{},[406,4004,4005],{},"Частичная сумма",[2039,4007,1750],{},[2039,4009,1733],{},[2039,4011,2159],{},[2039,4013,2145],{},[2039,4015,2212],{},[2039,4017,2045],{},[2039,4019,4020],{},"59",[426,4022,4023],{},"Теперь можно быстро отвечать на любой запрос, используя массив частичных сумм:\nдля вычисления суммы диапазона от индекса a до b нужно взять значение в индексе b и вычесть из него значение в индексе a – 1.\nДля диапазона от 2 до 5 получится 48 – 8 = 40, а от 1 до 6 получится 59 – 6 = 53.\nТеперь на получение ответов независимо от величины диапазона требуется одинаковое количество времени,\nпричем для этого достаточно было сделать всего один предварительный проход по массиву.",[426,4025,4026],{},[1075,4027,4028],{},[406,4029,4030],{},"Запрос суммы двумерного массива",[426,4032,4033],{},"Вернемся в двумерный мир наших рангов качества.\nСуммирование элементов каждого прямоугольника — слишком медленный процесс, поэтому мы расширим освоенный на одномерном примере прием до двух измерений.\nВ частности, потребуется создать новый массив, в котором индекс (i, j) является суммой элементов прямоугольника,\nкоординаты верхнего левого угла которого — (0, 0), а нижнего правого — (i, j).\nЕще раз взглянем на таблицу:",[2007,4035,4036,4056],{},[2010,4037,4038],{},[2013,4039,4040,4042,4044,4046,4048,4050,4052,4054],{},[2016,4041],{},[2016,4043,672],{},[2016,4045,683],{},[2016,4047,694],{},[2016,4049,2026],{},[2016,4051,1723],{},[2016,4053,1728],{},[2016,4055,1750],{},[2034,4057,4058,4078,4098,4118,4138,4158,4178],{},[2013,4059,4060,4064,4066,4068,4070,4072,4074,4076],{},[2039,4061,4062],{},[406,4063,672],{},[2039,4065,683],{},[2039,4067,3762],{},[2039,4069,3762],{},[2039,4071,683],{},[2039,4073,683],{},[2039,4075,683],{},[2039,4077,3762],{},[2013,4079,4080,4084,4086,4088,4090,4092,4094,4096],{},[2039,4081,4082],{},[406,4083,683],{},[2039,4085,683],{},[2039,4087,3762],{},[2039,4089,683],{},[2039,4091,683],{},[2039,4093,683],{},[2039,4095,3762],{},[2039,4097,683],{},[2013,4099,4100,4104,4106,4108,4110,4112,4114,4116],{},[2039,4101,4102],{},[406,4103,694],{},[2039,4105,683],{},[2039,4107,683],{},[2039,4109,683],{},[2039,4111,3762],{},[2039,4113,3762],{},[2039,4115,3762],{},[2039,4117,683],{},[2013,4119,4120,4124,4126,4128,4130,4132,4134,4136],{},[2039,4121,4122],{},[406,4123,2026],{},[2039,4125,3762],{},[2039,4127,683],{},[2039,4129,3762],{},[2039,4131,3762],{},[2039,4133,683],{},[2039,4135,3762],{},[2039,4137,683],{},[2013,4139,4140,4144,4146,4148,4150,4152,4154,4156],{},[2039,4141,4142],{},[406,4143,1723],{},[2039,4145,683],{},[2039,4147,683],{},[2039,4149,683],{},[2039,4151,3762],{},[2039,4153,683],{},[2039,4155,683],{},[2039,4157,683],{},[2013,4159,4160,4164,4166,4168,4170,4172,4174,4176],{},[2039,4161,4162],{},[406,4163,1728],{},[2039,4165,683],{},[2039,4167,683],{},[2039,4169,683],{},[2039,4171,3762],{},[2039,4173,683],{},[2039,4175,683],{},[2039,4177,3762],{},[2013,4179,4180,4184,4186,4188,4190,4192,4194,4196],{},[2039,4181,4182],{},[406,4183,1750],{},[2039,4185,683],{},[2039,4187,3762],{},[2039,4189,683],{},[2039,4191,683],{},[2039,4193,683],{},[2039,4195,683],{},[2039,4197,683],{},[426,4199,4200],{},"Соответствующий ей массив \"частичных сумм\" представлен в таблице ниже:",[2007,4202,4203,4223],{},[2010,4204,4205],{},[2013,4206,4207,4209,4211,4213,4215,4217,4219,4221],{},[2016,4208],{},[2016,4210,672],{},[2016,4212,683],{},[2016,4214,694],{},[2016,4216,2026],{},[2016,4218,1723],{},[2016,4220,1728],{},[2016,4222,1750],{},[2034,4224,4225,4245,4265,4285,4305,4325,4345],{},[2013,4226,4227,4231,4233,4235,4237,4239,4241,4243],{},[2039,4228,4229],{},[406,4230,672],{},[2039,4232,683],{},[2039,4234,672],{},[2039,4236,3762],{},[2039,4238,672],{},[2039,4240,683],{},[2039,4242,694],{},[2039,4244,683],{},[2013,4246,4247,4251,4253,4255,4257,4259,4261,4263],{},[2039,4248,4249],{},[406,4250,683],{},[2039,4252,694],{},[2039,4254,672],{},[2039,4256,672],{},[2039,4258,694],{},[2039,4260,1723],{},[2039,4262,1723],{},[2039,4264,1723],{},[2013,4266,4267,4271,4273,4275,4277,4279,4281,4283],{},[2039,4268,4269],{},[406,4270,694],{},[2039,4272,2026],{},[2039,4274,694],{},[2039,4276,2026],{},[2039,4278,1723],{},[2039,4280,1728],{},[2039,4282,1723],{},[2039,4284,1728],{},[2013,4286,4287,4291,4293,4295,4297,4299,4301,4303],{},[2039,4288,4289],{},[406,4290,2026],{},[2039,4292,694],{},[2039,4294,694],{},[2039,4296,694],{},[2039,4298,694],{},[2039,4300,1723],{},[2039,4302,694],{},[2039,4304,1723],{},[2013,4306,4307,4311,4313,4315,4317,4319,4321,4323],{},[2039,4308,4309],{},[406,4310,1723],{},[2039,4312,2026],{},[2039,4314,1723],{},[2039,4316,1728],{},[2039,4318,1723],{},[2039,4320,2104],{},[2039,4322,1750],{},[2039,4324,2107],{},[2013,4326,4327,4331,4333,4335,4337,4339,4341,4343],{},[2039,4328,4329],{},[406,4330,1728],{},[2039,4332,1723],{},[2039,4334,1750],{},[2039,4336,1733],{},[2039,4338,1750],{},[2039,4340,1016],{},[2039,4342,1016],{},[2039,4344,1764],{},[2013,4346,4347,4351,4353,4355,4357,4359,4361,4363],{},[2039,4348,4349],{},[406,4350,1750],{},[2039,4352,1728],{},[2039,4354,1750],{},[2039,4356,2107],{},[2039,4358,1733],{},[2039,4360,2128],{},[2039,4362,2120],{},[2039,4364,1048],{},[426,4366,4367],{},"Для начала убедимся, что правильно понимаем предоставляемые этим массивом данные, а потом уже перейдем к рассмотрению его построения.\nЗначение в строке 4 и столбце 2 указывает сумму чисел в прямоугольнике, координаты верхнего левого угла которого — (0, 0), а правого нижнего — (4, 2).\nКак вычислить значение для ячейки (4, 2) на основе других ранее вычисленных значений?\nНужно начать со значения из ячейки таблицы -1 и 1 и прибавить все числа выше, а также левее нее.\nЭто можно сделать, грамотно используя массив из таблицы \"частичных сумм\", как будет показано в таблице ниже.",[426,4369,4370],{},"Необходимо начать с 1, затем охватить ячейки, включающие x (выше), а также ячейки, включающие y (слева), после чего вычислить сумму.\nСумма ячеек, включающих x, представлена элементом (3, 2). Сумма ячеек, включающих y, аналогичным образом представлена элементом (4, 1).\nОднако их сложение приводит к двойному подсчету ячеек xy (расположенных выше и левее).\nНо это не проблема, потому что элемент (3, 1) содержит сумму именно этих ячеек и компенсировать двойной подсчет можно его вычитанием.\nТаким образом, получается 1 + 2 + 4 – 2 = 5, что нам и требовалось.\nПри условии продвижения сверху вниз и слева направо можно строить этот массив с помощью всего двух операций сложения и одной операции вычитания для каждой ячейки.",[2007,4372,4373,4393],{},[2010,4374,4375],{},[2013,4376,4377,4379,4381,4383,4385,4387,4389,4391],{},[2016,4378],{},[2016,4380,672],{},[2016,4382,683],{},[2016,4384,694],{},[2016,4386,2026],{},[2016,4388,1723],{},[2016,4390,1728],{},[2016,4392,1750],{},[2034,4394,4395,4417,4437,4457,4477,4498,4518],{},[2013,4396,4397,4401,4404,4406,4409,4411,4413,4415],{},[2039,4398,4399],{},[406,4400,672],{},[2039,4402,4403],{},"xy",[2039,4405,4403],{},[2039,4407,4408],{},"x",[2039,4410],{},[2039,4412],{},[2039,4414],{},[2039,4416],{},[2013,4418,4419,4423,4425,4427,4429,4431,4433,4435],{},[2039,4420,4421],{},[406,4422,683],{},[2039,4424,4403],{},[2039,4426,4403],{},[2039,4428,4408],{},[2039,4430],{},[2039,4432],{},[2039,4434],{},[2039,4436],{},[2013,4438,4439,4443,4445,4447,4449,4451,4453,4455],{},[2039,4440,4441],{},[406,4442,694],{},[2039,4444,4403],{},[2039,4446,4403],{},[2039,4448,4408],{},[2039,4450],{},[2039,4452],{},[2039,4454],{},[2039,4456],{},[2013,4458,4459,4463,4465,4467,4469,4471,4473,4475],{},[2039,4460,4461],{},[406,4462,2026],{},[2039,4464,4403],{},[2039,4466,4403],{},[2039,4468,4408],{},[2039,4470],{},[2039,4472],{},[2039,4474],{},[2039,4476],{},[2013,4478,4479,4483,4486,4488,4490,4492,4494,4496],{},[2039,4480,4481],{},[406,4482,1723],{},[2039,4484,4485],{},"y",[2039,4487,4485],{},[2039,4489,683],{},[2039,4491],{},[2039,4493],{},[2039,4495],{},[2039,4497],{},[2013,4499,4500,4504,4506,4508,4510,4512,4514,4516],{},[2039,4501,4502],{},[406,4503,1728],{},[2039,4505],{},[2039,4507],{},[2039,4509],{},[2039,4511],{},[2039,4513],{},[2039,4515],{},[2039,4517],{},[2013,4519,4520,4524,4526,4528,4530,4532,4534,4536],{},[2039,4521,4522],{},[406,4523,1750],{},[2039,4525],{},[2039,4527],{},[2039,4529],{},[2039,4531],{},[2039,4533],{},[2039,4535],{},[2039,4537],{},[426,4539,4540],{},"Теперь мы знаем, как создавать массив \"частичных сумм\", но что это дает?\nЭто позволяет быстро вычислять сумму элементов любого прямоугольника.\nПредположим, что нам нужна сумма для прямоугольника, координаты левого верхнего угла которого — (1, 3), а правого нижнего — (5, 5).\nНельзя просто использовать значение 10 в ячейке (5, 5).\nПомимо суммы ячеек нужного прямоугольника оно включает также элементы, находящиеся выше и слева.\nОднако, как и в одномерном случае, можно вычислить необходимое значение, чтобы оно включало элементы только интересующего нас прямоугольника.\nДанная операция отражена в таблице ниже, где ячейки нужного прямоугольника отмечены звездочками.\nНа этот раз нужно вычесть ячейки, включающие x, и ячейки, включающие y.\nСумму ячеек x содержит ячейка (0, 5), а ячеек y — (5, 2).\nНо вычитанием обеих этих сумм мы дважды вычтем ячейки xy, поэтому нужно прибавить значение ячейки (0, 2).\nТаким образом, получается 10 – 2 – 8 + (–1) = –1, что и является суммой ячеек нужного прямоугольника.",[2007,4542,4543,4563],{},[2010,4544,4545],{},[2013,4546,4547,4549,4551,4553,4555,4557,4559,4561],{},[2016,4548],{},[2016,4550,672],{},[2016,4552,683],{},[2016,4554,694],{},[2016,4556,2026],{},[2016,4558,1723],{},[2016,4560,1728],{},[2016,4562,1750],{},[2034,4564,4565,4585,4605,4625,4645,4665,4685],{},[2013,4566,4567,4571,4573,4575,4577,4579,4581,4583],{},[2039,4568,4569],{},[406,4570,672],{},[2039,4572,4403],{},[2039,4574,4403],{},[2039,4576,4403],{},[2039,4578,4408],{},[2039,4580,4408],{},[2039,4582,4408],{},[2039,4584],{},[2013,4586,4587,4591,4593,4595,4597,4599,4601,4603],{},[2039,4588,4589],{},[406,4590,683],{},[2039,4592,4485],{},[2039,4594,4485],{},[2039,4596,4485],{},[2039,4598,897],{},[2039,4600,897],{},[2039,4602,897],{},[2039,4604],{},[2013,4606,4607,4611,4613,4615,4617,4619,4621,4623],{},[2039,4608,4609],{},[406,4610,694],{},[2039,4612,4485],{},[2039,4614,4485],{},[2039,4616,4485],{},[2039,4618,897],{},[2039,4620,897],{},[2039,4622,897],{},[2039,4624],{},[2013,4626,4627,4631,4633,4635,4637,4639,4641,4643],{},[2039,4628,4629],{},[406,4630,2026],{},[2039,4632,4485],{},[2039,4634,4485],{},[2039,4636,4485],{},[2039,4638,897],{},[2039,4640,897],{},[2039,4642,897],{},[2039,4644],{},[2013,4646,4647,4651,4653,4655,4657,4659,4661,4663],{},[2039,4648,4649],{},[406,4650,1723],{},[2039,4652,4485],{},[2039,4654,4485],{},[2039,4656,4485],{},[2039,4658,897],{},[2039,4660,897],{},[2039,4662,897],{},[2039,4664],{},[2013,4666,4667,4671,4673,4675,4677,4679,4681,4683],{},[2039,4668,4669],{},[406,4670,1728],{},[2039,4672,4485],{},[2039,4674,4485],{},[2039,4676,4485],{},[2039,4678,897],{},[2039,4680,897],{},[2039,4682,897],{},[2039,4684],{},[2013,4686,4687,4691,4693,4695,4697,4699,4701,4703],{},[2039,4688,4689],{},[406,4690,1750],{},[2039,4692],{},[2039,4694],{},[2039,4696],{},[2039,4698],{},[2039,4700],{},[2039,4702],{},[2039,4704],{},[426,4706,4707],{},"Теперь можно объединить все воедино: идею с –1 и 1, построение массива частичных сумм и его использование для быстрого получения сумм прямоугольников.\nСоответствующий код дан ниже:",[525,4709,4711],{"className":527,"code":4710,"language":529,"meta":530,"style":530},"def can_make_quality(quality, r, c, h, w, q):\n    zero_one = [row[:] for row in q]\n    sum_q = [[0 for _ in range(c + 1)] for _ in range(r + 1)]\n    for i in range(r):\n        for j in range(c):\n            if q[i][j] \u003C= quality:\n                zero_one[i][j] = -1\n            else:\n                zero_one[i][j] = 1\n    for i in range(1, r + 1):\n        for j in range(1, c + 1):\n            sum_q[i][j] = zero_one[i - 1][j - 1] + sum_q[i - 1][j] + sum_q[i][j - 1] - sum_q[i - 1][j - 1]\n    for top_row in range(1, r - h + 2):\n        for left_col in range(1, c - w + 2):\n            bottom_row = top_row + h - 1\n            right_col = left_col + w - 1\n            total = sum_q[bottom_row][right_col] - sum_q[top_row-1][right_col] - sum_q[bottom_row][left_col-1] + sum_q[top_row-1][left_col-1]\n            if total \u003C= 0:\n                return True\n    return False\n",[532,4712,4713,4721,4737,4783,4795,4807,4817,4827,4833,4841,4864,4887,4949,4975,5001,5017,5033,5082,5094,5100],{"__ignoreMap":530},[535,4714,4715,4717,4719],{"class":537,"line":538},[535,4716,791],{"class":545},[535,4718,3448],{"class":794},[535,4720,3451],{"class":541},[535,4722,4723,4725,4727,4729,4731,4733,4735],{"class":537,"line":560},[535,4724,3456],{"class":541},[535,4726,546],{"class":545},[535,4728,3461],{"class":541},[535,4730,586],{"class":545},[535,4732,3466],{"class":541},[535,4734,592],{"class":545},[535,4736,3471],{"class":541},[535,4738,4739,4742,4744,4746,4748,4751,4753,4755,4757,4759,4761,4763,4766,4768,4770,4772,4774,4776,4778,4780],{"class":537,"line":583},[535,4740,4741],{"class":541},"    sum_q ",[535,4743,546],{"class":545},[535,4745,2326],{"class":541},[535,4747,672],{"class":549},[535,4749,4750],{"class":545}," for",[535,4752,1936],{"class":541},[535,4754,592],{"class":545},[535,4756,595],{"class":549},[535,4758,2780],{"class":541},[535,4760,1151],{"class":545},[535,4762,604],{"class":549},[535,4764,4765],{"class":541},")] ",[535,4767,586],{"class":545},[535,4769,1936],{"class":541},[535,4771,592],{"class":545},[535,4773,595],{"class":549},[535,4775,2755],{"class":541},[535,4777,1151],{"class":545},[535,4779,604],{"class":549},[535,4781,4782],{"class":541},")]\n",[535,4784,4785,4787,4789,4791,4793],{"class":537,"line":610},[535,4786,2745],{"class":545},[535,4788,589],{"class":541},[535,4790,592],{"class":545},[535,4792,595],{"class":549},[535,4794,3484],{"class":541},[535,4796,4797,4799,4801,4803,4805],{"class":537,"line":634},[535,4798,865],{"class":545},[535,4800,2647],{"class":541},[535,4802,592],{"class":545},[535,4804,595],{"class":549},[535,4806,3497],{"class":541},[535,4808,4809,4811,4813,4815],{"class":537,"line":655},[535,4810,919],{"class":545},[535,4812,3504],{"class":541},[535,4814,1672],{"class":545},[535,4816,3509],{"class":541},[535,4818,4819,4821,4823,4825],{"class":537,"line":666},[535,4820,3514],{"class":541},[535,4822,546],{"class":545},[535,4824,818],{"class":545},[535,4826,3521],{"class":549},[535,4828,4829,4831],{"class":537,"line":678},[535,4830,3526],{"class":545},[535,4832,823],{"class":541},[535,4834,4835,4837,4839],{"class":537,"line":689},[535,4836,3514],{"class":541},[535,4838,546],{"class":545},[535,4840,1620],{"class":549},[535,4842,4843,4845,4847,4849,4851,4853,4855,4858,4860,4862],{"class":537,"line":700},[535,4844,2745],{"class":545},[535,4846,589],{"class":541},[535,4848,592],{"class":545},[535,4850,595],{"class":549},[535,4852,571],{"class":541},[535,4854,683],{"class":549},[535,4856,4857],{"class":541},", r ",[535,4859,1151],{"class":545},[535,4861,604],{"class":549},[535,4863,607],{"class":541},[535,4865,4866,4868,4870,4872,4874,4876,4878,4881,4883,4885],{"class":537,"line":730},[535,4867,865],{"class":545},[535,4869,2647],{"class":541},[535,4871,592],{"class":545},[535,4873,595],{"class":549},[535,4875,571],{"class":541},[535,4877,683],{"class":549},[535,4879,4880],{"class":541},", c ",[535,4882,1151],{"class":545},[535,4884,604],{"class":549},[535,4886,607],{"class":541},[535,4888,4889,4892,4894,4897,4899,4901,4904,4906,4908,4910,4912,4915,4917,4919,4922,4924,4927,4929,4931,4933,4935,4937,4939,4941,4943,4945,4947],{"class":537,"line":742},[535,4890,4891],{"class":541},"            sum_q[i][j] ",[535,4893,546],{"class":545},[535,4895,4896],{"class":541}," zero_one[i ",[535,4898,601],{"class":545},[535,4900,604],{"class":549},[535,4902,4903],{"class":541},"][j ",[535,4905,601],{"class":545},[535,4907,604],{"class":549},[535,4909,812],{"class":541},[535,4911,1151],{"class":545},[535,4913,4914],{"class":541}," sum_q[i ",[535,4916,601],{"class":545},[535,4918,604],{"class":549},[535,4920,4921],{"class":541},"][j] ",[535,4923,1151],{"class":545},[535,4925,4926],{"class":541}," sum_q[i][j ",[535,4928,601],{"class":545},[535,4930,604],{"class":549},[535,4932,812],{"class":541},[535,4934,601],{"class":545},[535,4936,4914],{"class":541},[535,4938,601],{"class":545},[535,4940,604],{"class":549},[535,4942,4903],{"class":541},[535,4944,601],{"class":545},[535,4946,604],{"class":549},[535,4948,843],{"class":541},[535,4950,4951,4953,4955,4957,4959,4961,4963,4965,4967,4969,4971,4973],{"class":537,"line":1663},[535,4952,2745],{"class":545},[535,4954,2748],{"class":541},[535,4956,592],{"class":545},[535,4958,595],{"class":549},[535,4960,571],{"class":541},[535,4962,683],{"class":549},[535,4964,4857],{"class":541},[535,4966,601],{"class":545},[535,4968,2760],{"class":541},[535,4970,1151],{"class":545},[535,4972,1159],{"class":549},[535,4974,607],{"class":541},[535,4976,4977,4979,4981,4983,4985,4987,4989,4991,4993,4995,4997,4999],{"class":537,"line":3624},[535,4978,865],{"class":545},[535,4980,2773],{"class":541},[535,4982,592],{"class":545},[535,4984,595],{"class":549},[535,4986,571],{"class":541},[535,4988,683],{"class":549},[535,4990,4880],{"class":541},[535,4992,601],{"class":545},[535,4994,2785],{"class":541},[535,4996,1151],{"class":545},[535,4998,1159],{"class":549},[535,5000,607],{"class":541},[535,5002,5003,5005,5007,5009,5011,5013,5015],{"class":537,"line":3644},[535,5004,2796],{"class":541},[535,5006,546],{"class":545},[535,5008,2748],{"class":541},[535,5010,1151],{"class":545},[535,5012,2760],{"class":541},[535,5014,601],{"class":545},[535,5016,1620],{"class":549},[535,5018,5019,5021,5023,5025,5027,5029,5031],{"class":537,"line":3663},[535,5020,2813],{"class":541},[535,5022,546],{"class":545},[535,5024,2773],{"class":541},[535,5026,1151],{"class":545},[535,5028,2785],{"class":541},[535,5030,601],{"class":545},[535,5032,1620],{"class":549},[535,5034,5035,5037,5039,5042,5044,5047,5049,5051,5054,5056,5059,5061,5063,5065,5067,5069,5071,5073,5076,5078,5080],{"class":537,"line":3679},[535,5036,3617],{"class":541},[535,5038,546],{"class":545},[535,5040,5041],{"class":541}," sum_q[bottom_row][right_col] ",[535,5043,601],{"class":545},[535,5045,5046],{"class":541}," sum_q[top_row",[535,5048,601],{"class":545},[535,5050,683],{"class":549},[535,5052,5053],{"class":541},"][right_col] ",[535,5055,601],{"class":545},[535,5057,5058],{"class":541}," sum_q[bottom_row][left_col",[535,5060,601],{"class":545},[535,5062,683],{"class":549},[535,5064,812],{"class":541},[535,5066,1151],{"class":545},[535,5068,5046],{"class":541},[535,5070,601],{"class":545},[535,5072,683],{"class":549},[535,5074,5075],{"class":541},"][left_col",[535,5077,601],{"class":545},[535,5079,683],{"class":549},[535,5081,843],{"class":541},[535,5083,5084,5086,5088,5090,5092],{"class":537,"line":3693},[535,5085,919],{"class":545},[535,5087,3671],{"class":541},[535,5089,1672],{"class":545},[535,5091,3688],{"class":549},[535,5093,823],{"class":541},[535,5095,5096,5098],{"class":537,"line":3700},[535,5097,966],{"class":545},[535,5099,977],{"class":549},[535,5101,5103,5105],{"class":537,"line":5102},20,[535,5104,974],{"class":545},[535,5106,969],{"class":549},[426,5108,5109,5110,5112,5113,5116,5117,5119,5120,5214],{},"Вначале создается массив ",[532,5111,3710],{},", в точности как это делалось ранее в коде выше.\nВторым шагом идет создание массива частичных сумм ",[532,5114,5115],{},"sum_q",".\nМы будем использовать индексы, начинающиеся с 1, а не с 0, чтобы не пришлось беспокоиться о возможном выходе за границы массива при обработке ячеек в строке 0 или столбце 0.\nНа третьем шаге массив частичных сумм используется для быстрого вычисления суммы каждого прямоугольника.\nОбратите внимание, что любой прямоугольник здесь суммируется за одинаковое время.\nНа втором шаге мы выполнили предварительную обработку, которая в дальнейшем позволит узнать сумму для любого прямоугольника,\nне тратя времени на сложение всех его элементов.\nПо сравнению с кодом ранее мы удалили из циклов ",[532,5118,586],{}," два уровня вложения.\nСледовательно, у нас получился алгоритм ",[2940,5121,5123],{"className":5122,"jax":2944},[2943],[2946,5124,5126,5156],{"style":2948,"xmlns":2949,"width":3189,"height":2951,"role":441,"focusable":2952,"viewBox":5125,"xmlnsXLink":2954},"0 -833.9 5271.6 1083.9",[2956,5127,5128,5131,5134,5137,5140,5143,5146,5149,5152],{},[2959,5129],{"id":5130,"d":3002},"MJX-3-TEX-I-1D442",[2959,5132],{"id":5133,"d":2962},"MJX-3-TEX-N-28",[2959,5135],{"id":5136,"d":2966},"MJX-3-TEX-I-1D45A",[2959,5138],{"id":5139,"d":2970},"MJX-3-TEX-N-32",[2959,5141],{"id":5142,"d":2986},"MJX-3-TEX-I-1D459",[2959,5144],{"id":5145,"d":2990},"MJX-3-TEX-I-1D45C",[2959,5147],{"id":5148,"d":2994},"MJX-3-TEX-I-1D454",[2959,5150],{"id":5151,"d":2982},"MJX-3-TEX-N-29",[2959,5153],{"id":5154,"d":5155},"MJX-3-TEX-N-2C","M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z",[3008,5157,5158],{"stroke":3010,"fill":3010,"stroke-width":672,"transform":3011},[3008,5159,5160,5165,5170,5184,5189,5194,5199,5203,5208],{"dataMmlNode":3014},[3008,5161,5162],{"dataMmlNode":3028},[3019,5163],{"dataC":3131,"xLinkHref":5164},"#MJX-3-TEX-I-1D442",[3008,5166,5167],{"dataMmlNode":3017,"transform":3232},[3019,5168],{"dataC":2059,"xLinkHref":5169},"#MJX-3-TEX-N-28",[3008,5171,5172,5177],{"dataMmlNode":3024,"transform":3238},[3008,5173,5174],{"dataMmlNode":3028},[3019,5175],{"dataC":3031,"xLinkHref":5176},"#MJX-3-TEX-I-1D45A",[3008,5178,5179],{"dataMmlNode":3042,"transform":3036,"dataMjxTexclass":3043},[3008,5180,5181],{"dataMmlNode":3035},[3019,5182],{"dataC":2145,"xLinkHref":5183},"#MJX-3-TEX-N-32",[3008,5185,5186],{"dataMmlNode":3028,"transform":3253},[3019,5187],{"dataC":3068,"xLinkHref":5188},"#MJX-3-TEX-I-1D459",[3008,5190,5191],{"dataMmlNode":3028,"transform":3259},[3019,5192],{"dataC":3075,"xLinkHref":5193},"#MJX-3-TEX-I-1D45C",[3008,5195,5196],{"dataMmlNode":3028,"transform":3265},[3019,5197],{"dataC":3082,"xLinkHref":5198},"#MJX-3-TEX-I-1D454",[3008,5200,5201],{"dataMmlNode":3028,"transform":3271},[3019,5202],{"dataC":3031,"xLinkHref":5176},[3008,5204,5205],{"dataMmlNode":3017,"transform":3276},[3019,5206],{"dataC":2162,"xLinkHref":5207},"#MJX-3-TEX-N-29",[3008,5209,5210],{"dataMmlNode":3017,"transform":3282},[3019,5211],{"dataC":5212,"xLinkHref":5213},"2C","#MJX-3-TEX-N-2C"," который достаточно быстр.\nПопробуйте! А потом советую немного передохнуть, так как нас ждет еще одна серьезная задача.",[410,5216,5218],{"id":5217},"задача-4-двери-пещеры","Задача 4. Двери пещеры",[426,5220,5221],{},"Рассмотрим задачу, в которой двоичный поиск будет использоваться не для нахождения оптимального решения, а для выделения нужного элемента.",[402,5223,424],{"id":5224},"условие-3",[426,5226,5227,5228,5231,5232,5234],{},"Вы стоите перед входом в длинную узкую пещеру, через которую необходимо пробраться и достичь выхода.\nНа пути нужно пройти через n дверей: первая — это дверь 0, вторая — дверь 1 и т. д.\nКаждая дверь может быть открыта либо закрыта.\nЧерез открытые двери можно пройти, через закрытые — нельзя.\nТаким образом, если двери 0 и 1 открыты, а дверь 2 закрыта, то можно пройти только до двери 2,\nпричем вы не видите состояния следующих за ней дверей.\nУ входа в пещеру установлена панель с n рычагов.\nКак и двери, рычаги пронумерованы, начиная с 0. Каждый из них может быть в верхнем (0) или нижнем (1) положении.\nПри этом каждый рычаг связан с одной дверью, определяя, закрыта она или открыта.\nЕсли рычаг установлен в правильное положение, то соответствующая дверь открыта.\nВ противном случае эта дверь закрыта. Вам не известны ни связь рычагов с дверьми, ни правильные положения рычагов.\nК примеру, возможно, что рычаг 0 связан с дверью 5 и для ее открывания должен находиться в нижнем положении,\nа рычаг 1 связан с дверью 0 и для ее открывания должен находиться в верхнем положении.\nМожно устанавливать рычаги в желаемое положение, а затем проходить в пещеру для определения первой закрытой двери и возвращаться.\nПри этом запаса сил вам хватит максимум на 70 000 таких циклов.\nЦель — определить верное положение(0 или 1) каждого рычага и связанную с ним дверь.\nНужно написать следующую функцию: ",[532,5229,5230],{},"exploreCave(n)",".\nЗдесь ",[532,5233,2927],{}," является количеством дверей и рычагов (от 1 до 5000).\nДля реализации этой функции нужно будет вызвать две функции, предоставленные судьей.\nОни будут описаны далее.",[402,5236,454],{"id":5237},"входные-данные-3",[426,5239,5240,5241,5244,5245,5247,5248,5251,5252,5255,5256,5259,5260,5263],{},"Из стандартного ввода мы ничего не считываем.\nЕдинственный способ узнать исходные данные — это вызвать предоставленную судьей функцию tryCombination.\nВот ее сигнатура: ",[532,5242,5243],{},"tryCombination(switch_positions)",".\nПараметр switch_positions является массивом с длиной ",[532,5246,2927],{}," целых чисел, указывающим положение (0 или 1) каждого рычага.\nТо есть ",[532,5249,5250],{},"switch_positions[0]"," определяет положение рычага 0, ",[532,5253,5254],{},"switch_positions[1]"," — положение рычага 1 и т. д.\nФункция ",[532,5257,5258],{},"tryCombination"," симулирует ситуацию, в которой мы устанавливаем рычаги в ",[532,5261,5262],{},"switch_positions"," и проходим по пещере до первой закрытой двери.\nОна возвращает номер первой закрытой двери либо -1, если все двери открыты.",[402,5265,502],{"id":5266},"выходные-данные-3",[426,5268,5269,5270,5273,5274,5277,5278,5280,5281,5283,5284,5287,5288,5291,5292,5295,5296,5298],{},"В стандартный вывод запись не производится. Вместо этого мы отправляем ответ через вызов функции answer, также предоставленной судейским ресурсом.\nВот ее сигнатура: ",[532,5271,5272],{},"answer(switch_positions, door_for_switch)",".\nУ нас есть только одна попытка: при вызове ",[532,5275,5276],{},"answer"," наша программа уничтожается, так что правильный ответ следует отправлять с первого раза.\nПараметр ",[532,5279,5262],{}," — массив, содержащий предлагаемые нами положения рычагов в том же формате, что и ",[532,5282,5258],{},".\nПараметр ",[532,5285,5286],{},"door_for_switch"," содержит предлагаемые нами связи между рычагами и дверьми: ",[532,5289,5290],{},"door_for_switch[0]"," указывает дверь, связанную с рычагом 0,\n",[532,5293,5294],{},"door_for_switch[1]"," указывает дверь, связанную с рычагом 1, и т. д.\nВ данном случае ограничено не время, а количество вызовов ",[532,5297,5258],{},", которых допускается сделать на более 70 000.\nВ случае превышения этого значения программа завершается.",[402,5300,509],{"id":5301},"решение-3",[426,5303,5304],{},"Автор задачи разделил ее на пять подзадач. Пятая подзадача — это задача в общем виде.\nДругие подзадачи имеют дополнительные ограничения, упрощая решение.\nМне нравится, когда авторы задач используют подзадачи, особенно если у меня возникают сложности с поиском решения.\nВ таких случаях можно поочередно разделываться с каждой подзадачей, постепенно дорабатывая решение, пока не будет решена вся задача.\nПервая подзадача состоит в решении варианта, где каждый рычаг i связан с дверью под номером i.\nЭто значит, что рычаг 0 связан с дверью 0, рычаг 1 с дверью 1 и т. д.\nНам же нужно определить верное положение (0 или 1) для каждого рычага.",[426,5306,5307,5308,1225,5310,5312],{},"Начнем с подзадачи 1, чтобы иметь возможность вызывать судейские функции ",[532,5309,5258],{},[532,5311,5276],{},", а уже потом приступим к другим частям основной задачи.\nУ нас нет доступа к судейским функциям, но мы хотим протестировать свою работу локально.\nМожно запросить в Google «IOI 2013 tasks» и найти тестовые данные с шаблонами для задачи Cave. Вот пример:",[426,5314,5315],{},[441,5316],{"alt":5317,"src":5318},"Задача 4. Пример","\u002Fimages\u002Fblog\u002Fpython\u002Fst25\u002Fimg2.png",[426,5320,5321],{},"Данные оценщика для тестового примера:",[525,5323,5325],{"className":1419,"code":5324,"language":1421,"meta":530,"style":530},"4\n1110\n3102\n",[532,5326,5327,5331,5336],{"__ignoreMap":530},[535,5328,5329],{"class":537,"line":538},[535,5330,1464],{},[535,5332,5333],{"class":537,"line":560},[535,5334,5335],{},"1110\n",[535,5337,5338],{"class":537,"line":583},[535,5339,5340],{},"3102\n",[459,5342,5343,5346,5349],{},[462,5344,5345],{},"1 строка: N – количество дверей и переключателей;",[462,5347,5348],{},"2 строка: S[0]...S[3] – правильное положение переключателей с индексами 0-3;",[462,5350,5351],{},"3 строка: D[0]...D[3] – дверь, к которой подключен переключатель с индексами 0-3;",[426,5353,5354],{},[1075,5355,5356],{},[406,5357,5358],{},"ПРИМЕР СЕАНСА",[2007,5360,5361,5374],{},[2010,5362,5363],{},[2013,5364,5365,5368,5371],{},[2016,5366,5367],{},"Вызов функции",[2016,5369,5370],{},"Возврат",[2016,5372,5373],{},"Пояснение",[2034,5375,5376,5386,5396,5406],{},[2013,5377,5378,5381,5383],{},[2039,5379,5380],{},"tryCombination([1,0,1,1])",[2039,5382,683],{},[2039,5384,5385],{},"Это соответствует изображению. Переключатели 0, 2 и 3 опущены, а переключатель 1 поднят. Функция возвращает 1, что означает, что дверь 1 — первая закрытая дверь слева.",[2013,5387,5388,5391,5393],{},[2039,5389,5390],{},"tryCombination([0,1,1,0])",[2039,5392,2026],{},[2039,5394,5395],{},"Двери 0, 1 и 2 открыты, а дверь 3 закрыта.",[2013,5397,5398,5401,5403],{},[2039,5399,5400],{},"tryCombination([1,1,1,0])",[2039,5402,3762],{},[2039,5404,5405],{},"Перемещение переключателя 0 вниз приводит к открытию всех дверей, что подтверждается возвращаемым значением 1.",[2013,5407,5408,5411,5414],{},[2039,5409,5410],{},"answer([1,1,1,0],[3,1,0,2])",[2039,5412,5413],{},"выход из программы",[2039,5415,5416],{},"Мы предполагаем, что правильная комбинация — [1,1,1,0], и что переключатели 0, 1, 2 и 3 подключаются к дверям 3, 1, 0 и 2 соответственно.",[426,5418,5419],{},[1075,5420,5421],{},[406,5422,5423],{},"Эта задача стандартно решается на C\u002FC++ мы попробуем её также решить, но на Python.",[426,5425,5426],{},"Напишем код для подзадачи 1:",[525,5428,5430],{"className":527,"code":5429,"language":529,"meta":530,"style":530},"def exploreCave(n):\n  switch_positions = [0 for _ in range(n)]\n  door_for_switch = [i for i in range(n)]\n  for i in range(n):\n    result = tryCombination(switch_positions)\n    if result == i: # дверь i закрыта\n      switch_positions[i] = 1\n  answer(switch_positions, door_for_switch)\n",[532,5431,5432,5442,5464,5484,5496,5506,5522,5531],{"__ignoreMap":530},[535,5433,5434,5436,5439],{"class":537,"line":538},[535,5435,791],{"class":545},[535,5437,5438],{"class":794}," exploreCave",[535,5440,5441],{"class":541},"(n):\n",[535,5443,5444,5447,5449,5451,5453,5455,5457,5459,5461],{"class":537,"line":560},[535,5445,5446],{"class":541},"  switch_positions ",[535,5448,546],{"class":545},[535,5450,1716],{"class":541},[535,5452,672],{"class":549},[535,5454,4750],{"class":545},[535,5456,1936],{"class":541},[535,5458,592],{"class":545},[535,5460,595],{"class":549},[535,5462,5463],{"class":541},"(n)]\n",[535,5465,5466,5469,5471,5474,5476,5478,5480,5482],{"class":537,"line":583},[535,5467,5468],{"class":541},"  door_for_switch ",[535,5470,546],{"class":545},[535,5472,5473],{"class":541}," [i ",[535,5475,586],{"class":545},[535,5477,589],{"class":541},[535,5479,592],{"class":545},[535,5481,595],{"class":549},[535,5483,5463],{"class":541},[535,5485,5486,5488,5490,5492,5494],{"class":537,"line":610},[535,5487,1575],{"class":545},[535,5489,589],{"class":541},[535,5491,592],{"class":545},[535,5493,595],{"class":549},[535,5495,5441],{"class":541},[535,5497,5498,5501,5503],{"class":537,"line":634},[535,5499,5500],{"class":541},"    result ",[535,5502,546],{"class":545},[535,5504,5505],{"class":541}," tryCombination(switch_positions)\n",[535,5507,5508,5510,5513,5516,5519],{"class":537,"line":655},[535,5509,637],{"class":545},[535,5511,5512],{"class":541}," result ",[535,5514,5515],{"class":545},"==",[535,5517,5518],{"class":541}," i: ",[535,5520,5521],{"class":556},"# дверь i закрыта\n",[535,5523,5524,5527,5529],{"class":537,"line":666},[535,5525,5526],{"class":541},"      switch_positions[i] ",[535,5528,546],{"class":545},[535,5530,1620],{"class":549},[535,5532,5533],{"class":537,"line":678},[535,5534,5535],{"class":541},"  answer(switch_positions, door_for_switch)\n",[426,5537,5538],{},"Вначале положение каждого рычага устанавливается на 0, и дверь i связывается с рычагом i.\nПоложения рычагов мы будем обновлять при необходимости, а вот связь рычаг–дверь в данном случае (согласно ограничениям подзадачи) трогать не потребуется.\nЦикл for перебирает каждый рычаг. Его задача — определить, должен ли текущий рычаг остаться в положении 0 или переключиться в положение 1.\nРассмотрим первую итерацию, когда i равно 0. Вначале происходит вызов tryCombination, которая возвращает номер первой закрытой двери.\nЕсли возвращается 0, то рычаг 0 установлен неправильно.\nЕсли этот рычаг будет установлен верно, то дверь 0 окажется открыта и tryCombination вернет ненулевой номер двери.\nЕсли дверь 0 оказывается закрыта, мы изменяем положение рычага 0 с 0 на 1.\nВ результате дверь 0 открывается, и можно продвигаться к двери 1.\nНа следующем шаге i становится равной 1 и снова вызывается tryCombination.\nРезультат 0 в данном случае точно не вернется, потому что код уже проделал работу, гарантирующую открывание двери 0.\nЕсли возвращается 1, это означает, что дверь 1 закрыта и нужно изменить положение рычага 1 с 0 на 1.\nОбобщая, можно сказать, что в начале новой итерации цикла все двери до i (включая i – 1) открыты.\nЕсли дверь i закрыта, то мы изменяем положение рычага i с 0 на 1.\nЕсли дверь i уже открыта, значит, рычаг i установлен верно.\nЗакончив второй цикл for, мы выяснили верное положение каждого рычага.\nЭтот ответ мы передаем судейскому ресурсу через вызов функции answer.",[426,5540,5541],{},"Итак, в подзадаче 1 мы точно узнаём, какая дверь с каким рычагом связана.\nДля определения данного соответствия не требовалось выполнять поиск, но для решения всей задачи поиск нам понадобится,\nтак как неизвестно, какой рычаг за какую дверь отвечает.\nМы начнем с закрывания двери 0, после чего займемся перебором рычагов, чтобы открыть ее.\nДля этого будем последовательно изменять положение рычагов, проверяя, открылась или нет дверь 0.\nЕсли нет, то рычаг выбран ошибочно. Если же дверь 0 открылась, значит, связанный с ней рычаг найден.\nС этого момента дверь 0 остается открытой, и тот же процесс повторяется для двери 1:\nвначале она закрывается, а затем перебираются оставшиеся рычаги в поиске того, который ее откроет.",[426,5543,5544],{},"Начнем с нового кода exploreCave, приведенного ниже. Он краток, потому что перекладывает поиск на вспомогательную функцию.",[525,5546,5548],{"className":527,"code":5547,"language":529,"meta":530,"style":530},"def exploreCave(n):\n  switch_positions = [0 for _ in range(n)]\n  door_for_switch = [-1 for i in range(n)]\n  for i in range(n):\n    set_a_switch(i, switch_positions, door_for_switch, n)\n  answer(switch_positions, door_for_switch)\n",[532,5549,5550,5558,5578,5600,5612,5617],{"__ignoreMap":530},[535,5551,5552,5554,5556],{"class":537,"line":538},[535,5553,791],{"class":545},[535,5555,5438],{"class":794},[535,5557,5441],{"class":541},[535,5559,5560,5562,5564,5566,5568,5570,5572,5574,5576],{"class":537,"line":560},[535,5561,5446],{"class":541},[535,5563,546],{"class":545},[535,5565,1716],{"class":541},[535,5567,672],{"class":549},[535,5569,4750],{"class":545},[535,5571,1936],{"class":541},[535,5573,592],{"class":545},[535,5575,595],{"class":549},[535,5577,5463],{"class":541},[535,5579,5580,5582,5584,5586,5588,5590,5592,5594,5596,5598],{"class":537,"line":583},[535,5581,5468],{"class":541},[535,5583,546],{"class":545},[535,5585,1716],{"class":541},[535,5587,601],{"class":545},[535,5589,683],{"class":549},[535,5591,4750],{"class":545},[535,5593,589],{"class":541},[535,5595,592],{"class":545},[535,5597,595],{"class":549},[535,5599,5463],{"class":541},[535,5601,5602,5604,5606,5608,5610],{"class":537,"line":610},[535,5603,1575],{"class":545},[535,5605,589],{"class":541},[535,5607,592],{"class":545},[535,5609,595],{"class":549},[535,5611,5441],{"class":541},[535,5613,5614],{"class":537,"line":634},[535,5615,5616],{"class":541},"    set_a_switch(i, switch_positions, door_for_switch, n)\n",[535,5618,5619],{"class":537,"line":655},[535,5620,5535],{"class":541},[426,5622,5623,5624,5626,5627,5629,5630,5632,5633,5635,5636,5638,5639,5642,5643,5646],{},"Как и при решении подзадачи 1, каждый элемент ",[532,5625,5262],{}," будет хранить значения указывающие положение каждого рычага.\nПоложение всех рычагов устанавливается как ",[532,5628,672],{},"(если рычаг уже связан с дверью, его положение больше никогда не должно меняться).\nМассив ",[532,5631,5286],{}," указывает, какая дверь с каким рычагом соединена.\nИзначально каждый элемент ",[532,5634,5286],{}," инициализируется как ",[532,5637,3762],{},", поскольку все связи дверей с рычагами неизвестны.\nКогда становится известна связанная с рычагом ",[532,5640,5641],{},"i"," дверь, ",[532,5644,5645],{},"door_for_switch[i]"," должен будет обновляться.",[426,5648,5649],{},"А вот контрольный вопрос: если door_for_switch[5] равна 6, то что это значит?\nЗначит ли это, что рычаг 5 связан с дверью 6 или что дверь 5 связана с рычагом 6?\nПервый вариант! Запомните это, прежде чем продолжать.",[426,5651,5652,5653,5655,5656,5659],{},"Для каждой двери ",[532,5654,5641],{}," мы вызываем вспомогательную функцию ",[532,5657,5658],{},"set_a_switch",".\nЕе задача — выполнить поиск по рычагам и найти связанный с дверью i.\nОна также определяет, должен рычаг находиться в положении 0 или 1.",[520,5661,3293],{"id":5662},"двоичный-поиск-1",[426,5664,5665],{},"Числа 5000 (максимальное количество дверей) и 70 000 (максимум попыток подбора) тонко намекают на необходимость применения для решения стратегии двоичного поиска.\nОбратите внимание, что lb5000 округляется до 13.\nЕсли мы найдем способ использовать двоичный поиск, то он сможет подбирать верный рычаг для текущей двери всего за 13 шагов, но никак не за 5000(линейный поиск).\nЕсли на каждую дверь нам потребуется по 13 шагов, то при 5000 дверей получится 13 × 5000 = 65 000 шагов в общем.\nТаким образом, мы впишемся в лимит 70 000.",[426,5667,5668],{},"Как же здесь использовать двоичный поиск? Процесс должен позволить отбрасывать на каждом шаге половину диапазона рычагов.\nПоясню идею на примере. Предположим, что у нас восемь дверей и восемь рычагов, а также что дверь 0 в текущий момент закрыта.\nЕсли мы переключим рычаг 0 и дверь 0 не откроется, то из этого мы поймем немногое: только то, что рычаг 0 не связан с дверью 0\n(все равно что сказать «1» при угадывании загаданного кем-то числа между 1 и 1000).\nБолее удачной идеей будет переключить половину рычагов, так что давайте переключим рычаги 0, 1, 2 и 3.\nНезависимо от того, как это повлияет на дверь 0, мы узнаем уже очень многое.\nЕсли дверь по-прежнему останется закрыта, то рычаги с 0 по 3 к ней отношения не имеют и можно сосредоточиться на оставшейся половине рычагов с 4 по 7.\nЕсли же дверь 0 откроется, то станет ясно, что с ней связан один из рычагов с 0 по 3 и нужно более плотно сосредоточиться именно на них.\nЗа один шаг мы сразу отсекаем половину диапазона.\nПродолжая таким же путем дальнейший поиск, мы в конечном итоге определим рычаг, связанный с дверью 0 (и его положение).\nПредположим, что проделываем весь этот путь, снова и снова уменьшая диапазон рычагов в два раза, пока не останется всего один рычаг.\nДопустим, что связанным с дверью 0 оказался рычаг 6. Тогда мы установим его в положение, при котором дверь 0 будет открыта.\nВ этом положении он и останется.\nКогда далее мы перейдем к обработке двери 1 или любой другой двери впоследствии, то предусмотрительно не станем менять положение рычага 6.",[426,5670,5671],{},"Теперь я могу представить решение для этой задачи, основанное на двоичном поиске. Код set_a_switch приведен ниже:",[525,5673,5675],{"className":527,"code":5674,"language":529,"meta":530,"style":530},"def set_a_switch(door, switch_positions, door_for_switch, n):\n  low, high = 0, n - 1\n\n  result = tryCombination(switch_positions)\n  if result != door:\n    for i in range(n):\n      if door_for_switch[i] == -1:\n        switch_positions[i] = 1\n\n  while low != high:\n    mid = (low + high) \u002F\u002F 2\n    for i in range(low, mid + 1):\n      if door_for_switch[i] == -1:\n        switch_positions[i] = 1 - switch_positions[i]\n    result = tryCombination(switch_positions)\n    if result != door:\n      high = mid\n      for i in range(low, mid + 1):\n        if door_for_switch[i] == -1:\n          switch_positions[i] = 1 - switch_positions[i]\n    else:\n      low = mid + 1\n  door_for_switch[low] = door\n  switch_positions[low] = 1 - switch_positions[low]\n",[532,5676,5677,5687,5703,5709,5718,5729,5741,5757,5766,5770,5781,5797,5816,5830,5843,5851,5861,5869,5888,5902,5915,5922,5936,5947],{"__ignoreMap":530},[535,5678,5679,5681,5684],{"class":537,"line":538},[535,5680,791],{"class":545},[535,5682,5683],{"class":794}," set_a_switch",[535,5685,5686],{"class":541},"(door, switch_positions, door_for_switch, n):\n",[535,5688,5689,5692,5694,5696,5699,5701],{"class":537,"line":560},[535,5690,5691],{"class":541},"  low, high ",[535,5693,546],{"class":545},[535,5695,3688],{"class":549},[535,5697,5698],{"class":541},", n ",[535,5700,601],{"class":545},[535,5702,1620],{"class":549},[535,5704,5705],{"class":537,"line":583},[535,5706,5708],{"emptyLinePlaceholder":5707},true,"\n",[535,5710,5711,5714,5716],{"class":537,"line":610},[535,5712,5713],{"class":541},"  result ",[535,5715,546],{"class":545},[535,5717,5505],{"class":541},[535,5719,5720,5722,5724,5726],{"class":537,"line":634},[535,5721,1555],{"class":545},[535,5723,5512],{"class":541},[535,5725,815],{"class":545},[535,5727,5728],{"class":541}," door:\n",[535,5730,5731,5733,5735,5737,5739],{"class":537,"line":655},[535,5732,2745],{"class":545},[535,5734,589],{"class":541},[535,5736,592],{"class":545},[535,5738,595],{"class":549},[535,5740,5441],{"class":541},[535,5742,5743,5746,5749,5751,5753,5755],{"class":537,"line":666},[535,5744,5745],{"class":545},"      if",[535,5747,5748],{"class":541}," door_for_switch[i] ",[535,5750,5515],{"class":545},[535,5752,818],{"class":545},[535,5754,683],{"class":549},[535,5756,823],{"class":541},[535,5758,5759,5762,5764],{"class":537,"line":678},[535,5760,5761],{"class":541},"        switch_positions[i] ",[535,5763,546],{"class":545},[535,5765,1620],{"class":549},[535,5767,5768],{"class":537,"line":689},[535,5769,5708],{"emptyLinePlaceholder":5707},[535,5771,5772,5774,5776,5778],{"class":537,"line":700},[535,5773,1817],{"class":545},[535,5775,1126],{"class":541},[535,5777,815],{"class":545},[535,5779,5780],{"class":541}," high:\n",[535,5782,5783,5785,5787,5789,5791,5793,5795],{"class":537,"line":730},[535,5784,1834],{"class":541},[535,5786,546],{"class":545},[535,5788,1148],{"class":541},[535,5790,1151],{"class":545},[535,5792,1154],{"class":541},[535,5794,1845],{"class":545},[535,5796,1848],{"class":549},[535,5798,5799,5801,5803,5805,5807,5810,5812,5814],{"class":537,"line":742},[535,5800,2745],{"class":545},[535,5802,589],{"class":541},[535,5804,592],{"class":545},[535,5806,595],{"class":549},[535,5808,5809],{"class":541},"(low, mid ",[535,5811,1151],{"class":545},[535,5813,604],{"class":549},[535,5815,607],{"class":541},[535,5817,5818,5820,5822,5824,5826,5828],{"class":537,"line":1663},[535,5819,5745],{"class":545},[535,5821,5748],{"class":541},[535,5823,5515],{"class":545},[535,5825,818],{"class":545},[535,5827,683],{"class":549},[535,5829,823],{"class":541},[535,5831,5832,5834,5836,5838,5840],{"class":537,"line":3624},[535,5833,5761],{"class":541},[535,5835,546],{"class":545},[535,5837,604],{"class":549},[535,5839,818],{"class":545},[535,5841,5842],{"class":541}," switch_positions[i]\n",[535,5844,5845,5847,5849],{"class":537,"line":3644},[535,5846,5500],{"class":541},[535,5848,546],{"class":545},[535,5850,5505],{"class":541},[535,5852,5853,5855,5857,5859],{"class":537,"line":3663},[535,5854,637],{"class":545},[535,5856,5512],{"class":541},[535,5858,815],{"class":545},[535,5860,5728],{"class":541},[535,5862,5863,5865,5867],{"class":537,"line":3679},[535,5864,1875],{"class":541},[535,5866,546],{"class":545},[535,5868,1187],{"class":541},[535,5870,5871,5874,5876,5878,5880,5882,5884,5886],{"class":537,"line":3693},[535,5872,5873],{"class":545},"      for",[535,5875,589],{"class":541},[535,5877,592],{"class":545},[535,5879,595],{"class":549},[535,5881,5809],{"class":541},[535,5883,1151],{"class":545},[535,5885,604],{"class":549},[535,5887,607],{"class":541},[535,5889,5890,5892,5894,5896,5898,5900],{"class":537,"line":3700},[535,5891,1167],{"class":545},[535,5893,5748],{"class":541},[535,5895,5515],{"class":545},[535,5897,818],{"class":545},[535,5899,683],{"class":549},[535,5901,823],{"class":541},[535,5903,5904,5907,5909,5911,5913],{"class":537,"line":5102},[535,5905,5906],{"class":541},"          switch_positions[i] ",[535,5908,546],{"class":545},[535,5910,604],{"class":549},[535,5912,818],{"class":545},[535,5914,5842],{"class":541},[535,5916,5918,5920],{"class":537,"line":5917},21,[535,5919,1625],{"class":545},[535,5921,823],{"class":541},[535,5923,5925,5927,5929,5932,5934],{"class":537,"line":5924},22,[535,5926,1860],{"class":541},[535,5928,546],{"class":545},[535,5930,5931],{"class":541}," mid ",[535,5933,1151],{"class":545},[535,5935,1620],{"class":549},[535,5937,5939,5942,5944],{"class":537,"line":5938},23,[535,5940,5941],{"class":541},"  door_for_switch[low] ",[535,5943,546],{"class":545},[535,5945,5946],{"class":541}," door\n",[535,5948,5950,5953,5955,5957,5959],{"class":537,"line":5949},24,[535,5951,5952],{"class":541},"  switch_positions[low] ",[535,5954,546],{"class":545},[535,5956,604],{"class":549},[535,5958,818],{"class":545},[535,5960,5961],{"class":541}," switch_positions[low]\n",[426,5963,5964,5965,1225,5967,5969,5970,5973],{},"Вначале заводим переменные ",[532,5966,1224],{},[532,5968,1228],{}," необходимые для двоичного поиска и первый раз запустим функцию ",[532,5971,5972],{},"result = tryCombination(switch_positions)",".\nУстановив все еще не связанные рычаги в положение 0, мы определяем, открыта или нет текущая дверь.\nЕсли открыта, то нужно ее закрыть, чтобы потом путем поочередного изменения положения рычагов определить, какой из них ее откроет.\nДля закрывания двери мы устанавливаем все несвязанные рычаги в положение 1.\nТакой прием срабатывает, потому что, когда все рычаги находились в положении 0, дверь была открыта.\nОдин из этих рычагов связан с этой дверью, значит, при изменении их положения она точно закроется.",[426,5975,5976,5977,5980],{},"При каждой проверке условия двоичного поиска в цикле ",[532,5978,5979],{},"while"," мы делаем так, чтобы текущая дверь была закрыта.\nВ частности, когда low и high равны и цикл завершается, дверь остается закрытой.\nТогда останется лишь изменить положение рычага low, чтобы ее открыть.",[426,5982,5983,5984,5986],{},"Теперь рассмотрим сам двоичный поиск. В каждой итерации мы вычисляем среднюю точку ",[532,5985,1273],{},", затем изменяем положение первой половины рычагов(но только тех, которые еще не связаны с дверью).\nКакой эффект это оказало на текущую дверь? Здесь есть две возможности:",[459,5988,5989,6003],{},[462,5990,5991,5994,5995,1225,5997,5999,6000,6002],{},[406,5992,5993],{},"Дверь открылась."," Теперь нам известно, что искомый рычаг находится между ",[532,5996,1224],{},[532,5998,1273],{},", значит, все рычаги больше ",[532,6001,1273],{}," отбрасываются.\nМы также возвращаем каждый рычаг между low и mid обратно в положение, предшествовавшее текущей итерации.\nВ итоге дверь снова закрывается, и можно переходить к очередной итерации.",[462,6004,6005,6008],{},[406,6006,6007],{},"Дверь осталась закрыта."," Значит, искомый рычаг находится между mid + 1 и high, поэтому мы отбрасываем все рычаги, начиная с mid и менее.\nВ данном случае никакие рычаги не переключаются, потому что дверь по-прежнему закрыта, что нам и нужно.",[426,6010,6011],{},"По завершении двоичного поиска low и high будут равны, указывая на рычаг, связанный с текущей дверью.\nТекущая дверь в этот момент будет все еще закрыта, и мы переключим найденный рычаг для ее открытия.\nМы получили чистое, быстрое решение, основанное на двоичном поиске.",[410,6013,6015],{"id":6014},"выводы","Выводы",[426,6017,6018],{},"Иногда найти оптимальное решение намного сложнее, чем проверить допустимость одного из его вариантов.\nСколько жидкости нужно залить в дерево? Неизвестно. Будет ли достаточно 10 литров? А вот это уже можно проверить.\nПри правильных условиях двоичный поиск способен преобразовать сложную задачу оптимизации в намного более простую задачу проверки допустимости.\nИногда это похоже на жульничество. Добавление двоичного поиска означает всего лишь необходимость учитывать дополнительный логарифмический фактор.\nНо этот фактор практически не требует ресурсов, зато взамен мы получаем более простую задачу.\nЯ не утверждаю, что двоичный поиск является единственным способом решения задач из примеров выше.\nНекоторые задачи, которые можно решить с помощью двоичного поиска, также можно решить и через динамическое программирование.\nНо двоичный поиск часто может предложить решения, которые окажутся конкурентноспособными и более простыми, чем их альтернативы.\nЕсли вам интересно, вернитесь к каждой задаче еще раз, но теперь подумайте, как можно их решить без двоичного поиска.\nИ если вы видите задачу, в которой можно использовать двоичный поиск, то не стоит сомневаться.",[6020,6021,6022],"style",{},"\nmjx-container[jax=\"SVG\"] {\n  direction: ltr;\n}\n\nmjx-container[jax=\"SVG\"] > svg {\n  overflow: visible;\n  min-height: 1px;\n  min-width: 1px;\n}\n\nmjx-container[jax=\"SVG\"] > svg a {\n  fill: blue;\n  stroke: blue;\n}\n\nmjx-container[jax=\"SVG\"][display=\"true\"] {\n  display: block;\n  text-align: center;\n  margin: 1em 0;\n}\n\nmjx-container[jax=\"SVG\"][display=\"true\"][width=\"full\"] {\n  display: flex;\n}\n\nmjx-container[jax=\"SVG\"][justify=\"left\"] {\n  text-align: left;\n}\n\nmjx-container[jax=\"SVG\"][justify=\"right\"] {\n  text-align: right;\n}\n\ng[data-mml-node=\"merror\"] > g {\n  fill: red;\n  stroke: red;\n}\n\ng[data-mml-node=\"merror\"] > rect[data-background] {\n  fill: yellow;\n  stroke: none;\n}\n\ng[data-mml-node=\"mtable\"] > line[data-line], svg[data-table] > g > line[data-line] {\n  stroke-width: 70px;\n  fill: none;\n}\n\ng[data-mml-node=\"mtable\"] > rect[data-frame], svg[data-table] > g > rect[data-frame] {\n  stroke-width: 70px;\n  fill: none;\n}\n\ng[data-mml-node=\"mtable\"] > .mjx-dashed, svg[data-table] > g > .mjx-dashed {\n  stroke-dasharray: 140;\n}\n\ng[data-mml-node=\"mtable\"] > .mjx-dotted, svg[data-table] > g > .mjx-dotted {\n  stroke-linecap: round;\n  stroke-dasharray: 0,140;\n}\n\ng[data-mml-node=\"mtable\"] > g > svg {\n  overflow: visible;\n}\n\n[jax=\"SVG\"] mjx-tool {\n  display: inline-block;\n  position: relative;\n  width: 0;\n  height: 0;\n}\n\n[jax=\"SVG\"] mjx-tool > mjx-tip {\n  position: absolute;\n  top: 0;\n  left: 0;\n}\n\nmjx-tool > mjx-tip {\n  display: inline-block;\n  padding: .2em;\n  border: 1px solid #888;\n  font-size: 70%;\n  background-color: #F8F8F8;\n  color: black;\n  box-shadow: 2px 2px 5px #AAAAAA;\n}\n\ng[data-mml-node=\"maction\"][data-toggle] {\n  cursor: pointer;\n}\n\nmjx-status {\n  display: block;\n  position: fixed;\n  left: 1em;\n  bottom: 1em;\n  min-width: 25%;\n  padding: .2em .4em;\n  border: 1px solid #888;\n  font-size: 90%;\n  background-color: #F8F8F8;\n  color: black;\n}\n\nforeignObject[data-mjx-xml] {\n  font-family: initial;\n  line-height: normal;\n  overflow: visible;\n}\n\nmjx-container[jax=\"SVG\"] path[data-c], mjx-container[jax=\"SVG\"] use[data-c] {\n  stroke-width: 3;\n}\n",[6020,6024,6025],{},"html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sB1qb, html code.shiki .sB1qb{--shiki-default:#B31D28;--shiki-default-font-style:italic}",{"title":530,"searchDepth":560,"depth":634,"links":6027},[6028],{"id":399,"depth":560,"text":400,"children":6029},[6030,6031,6032,6043,6053,6063,6071],{"id":404,"depth":634,"text":408},{"id":412,"depth":610,"text":416},{"id":419,"depth":610,"text":420,"children":6033},[6034,6035,6036,6037],{"id":423,"depth":634,"text":424},{"id":453,"depth":634,"text":454},{"id":501,"depth":634,"text":502},{"id":508,"depth":634,"text":509,"children":6038},[6039,6040,6041,6042],{"id":522,"depth":655,"text":523},{"id":756,"depth":655,"text":757},{"id":1066,"depth":655,"text":1067},{"id":1344,"depth":655,"text":1345},{"id":1378,"depth":610,"text":1379,"children":6044},[6045,6046,6047,6048],{"id":1385,"depth":634,"text":424},{"id":1391,"depth":634,"text":454},{"id":1397,"depth":634,"text":502},{"id":1403,"depth":634,"text":509,"children":6049},[6050,6051,6052],{"id":1481,"depth":655,"text":1482},{"id":1773,"depth":655,"text":1067},{"id":1893,"depth":655,"text":523},{"id":1976,"depth":610,"text":1977,"children":6054},[6055,6056,6057,6058],{"id":1983,"depth":634,"text":424},{"id":2224,"depth":634,"text":454},{"id":2289,"depth":634,"text":502},{"id":2295,"depth":634,"text":509,"children":6059},[6060,6061,6062],{"id":3292,"depth":655,"text":3293},{"id":3422,"depth":655,"text":1482},{"id":3723,"depth":655,"text":3724},{"id":5217,"depth":610,"text":5218,"children":6064},[6065,6066,6067,6068],{"id":5224,"depth":634,"text":424},{"id":5237,"depth":634,"text":454},{"id":5266,"depth":634,"text":502},{"id":5301,"depth":634,"text":509,"children":6069},[6070],{"id":5662,"depth":655,"text":3293},{"id":6014,"depth":610,"text":6015},"2025-10-04","Примеры задач с использованием бинарного(двоичного) поиска","md","images\u002Fblog\u002Fpython\u002Fst25\u002Fimg.png",{},111,25,{"title":258,"description":6073},"kIoZJhRZoYvztfFnfni65_E9Cv93f5s_cWc-Uj6Ty04",[6082,6084],{"title":254,"path":255,"stem":256,"description":6083,"children":-1},"Введение. Реализация алгоритма бинарного поиска. Время выполнения алгоритмов",{"title":262,"path":263,"stem":264,"description":6085,"children":-1},"Алгоритм сортировки выбором массива или списка",1780737510288]