Advertisement
Guest User

Untitled

a guest
May 20th, 2018
520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.16 KB | None | 0 0
  1. /*
  2. Задано дерево с корнем, содержащее 𝑛 (1 ≤ 𝑛 ≤ 100 000) вершин, пронумерованных от 0 до 𝑛−1.
  3. Требуется ответить на 𝑚 (1 ≤ 𝑚 ≤ 10 000 000) запросов о наименьшем общем предке для пары вершин.
  4. Запросы генерируются следующим образом. Заданы числа 𝑎1, 𝑎2 и числа 𝑥, 𝑦 и 𝑧.
  5. Числа 𝑎3, . . . , 𝑎2𝑚 генерируются следующим образом: 𝑎𝑖 = (𝑥·𝑎𝑖−2+𝑦·𝑎𝑖−1+𝑧) mod 𝑛.
  6. Первый запрос имеет вид ⟨𝑎1, 𝑎2⟩.
  7. Если ответ на 𝑖−1-й запрос равен 𝑣, то 𝑖-й запрос имеет вид ⟨(𝑎2𝑖−1 + 𝑣) mod 𝑛, 𝑎2𝑖⟩.
  8. Для решения задачи можно использовать метод двоичного подъёма.
  9.  
  10. Формат входных данных:
  11. ---Первая строка содержит два числа: 𝑛 и 𝑚. Корень дерева имеет номер 0.
  12. ---Вторая строка содержит 𝑛 − 1 целых чисел, 𝑖-е из этих чисел равно номеру родителя вершины 𝑖.
  13. ---Третья строка содержит два целых числа в диапазоне от 0 до 𝑛−1: 𝑎1 и 𝑎2.
  14. ---Четвертая строка содержит три целых числа: 𝑥, 𝑦 и 𝑧, эти числа неотрицательны и не превосходят 109.
  15.  
  16. Формат выходных данных:
  17. ---Выведите в выходной файл сумму номеров вершин — ответов на все запросы.
  18. */
  19. /*
  20. Решение:
  21. -сохраняем дерево в список смежности
  22. -создаем пустой массив вершин (way) - 'хронологию' обхода
  23. -создаем массив индексов (pos) - pos[i] - первое вхождение вершины i в массив way
  24. -обходим дерево в глубину. Во время обхода, попав в очередную вершину(в том числе и корень):
  25. --если мы попали в вершину впервые:
  26. ---записываем ее в массив way (ее номер и ее глубину)
  27. ---записываем ее индекс в массиве way(хронологии) в массив pos(индексов)
  28. --иначе(попали в вершину повторно, вернувшись из рекурсии)
  29. ---записываем ее в массив way (кажый раз когда возвращаемся в нее)
  30. -после обхода хронология (массив way) содержит (степень вершины)
  31. --экземпляров каждой вершины в порядке обхода
  32. ----------
  33. -заметим интересную вещь. Рассмотрим участок хронологии от pos[a] до pos[b] включительно
  34. --в нем хранится хронология обхода от первого посещения a до первого посещения b
  35. --а значит в нем хранятся:
  36. ---все дети(и дети детей и т.д.) a и b
  37. ---все предки a и b вплоть до первого общего предка
  38. --то есть достаточно пройтись по участку от way[pos[a]] до way[pos[b]]
  39. ---и найти вершину с наимельшей глубиной. Это и будет LCA для a и b
  40. ----------
  41. -заносим way в sparce table
  42. -готовимся искать RMQ
  43. -далее на запрос a, b отвечаем RMQ(way[min(pos[a],pos[b])], way[max(pos[a],pos[b])])
  44. */
  45.  
  46.  
  47. #include <iostream>
  48. #include <vector>
  49. #include <algorithm>
  50. #include <utility>
  51. #include <cassert>
  52.  
  53. using namespace std;
  54.  
  55. //в sparse table будут храниться не только числа(минимумы), но и их индексы в массиве
  56. // это нужно для удобства поиска 2 минимума
  57. //element хранятся в sparse_table
  58. struct element {
  59. //номер вершины
  60. int num;
  61. //глубина вершины
  62. int depth;
  63. //конструктор от значения и индекса
  64. element(int _num = 0, int _depth = -1) : num(_num), depth(_depth) {}
  65. //конструктор от другого element
  66. element(const element& elem) : num(elem.num), depth(elem.depth) {}
  67. //операторы = и <
  68. element& operator=(const element& right) {
  69. num = right.num; depth = right.depth;
  70. return *this;
  71. }
  72. bool operator<(const element& right) const {
  73. return depth < right.depth;
  74. }
  75. };
  76.  
  77. //Разреженная таблица
  78. class sparce_table {
  79. private:
  80. //длина отрезка
  81. int N;
  82. //логарифм от длины отрезка по основанию 2
  83. int logN;
  84. //значения, хранящиеся в таблице
  85. vector<vector<element>> buffer;
  86. //логарифм по основанию 2 с округлением вниз
  87. //например log(10)=log(8)=3
  88. int log(const int val) const {
  89. if (val == 1) return 0;
  90. return log(val / 2) + 1;
  91. }
  92. public:
  93. sparce_table(vector<element>& data) : N(data.size()) {
  94. //инициализация таблицы:
  95.  
  96. //шаг 0: подготовка
  97. logN = log(N);
  98. buffer.assign(N, vector<element>());
  99.  
  100. //шаг 1: если отрезок состоит из 1 числа - оно и есть минимальный элемент
  101. for (int i = 0; i < N; i++) {
  102. buffer[i].push_back(data[i]);
  103. }
  104.  
  105.  
  106. //шаг2: мы уже знаем минимальные элементы для первой и второй половин отрезка
  107. // наименьший из них будет наименьшим для всего отрезка
  108. //сначала рассматриваем отрезки длины 1, потом 2 и т.д.
  109. for (int j = 1; j < logN + 1; j++) {
  110. //i-индекс начала отрезка
  111. for (int i = 0; i < N; i++) {
  112. //индекс конца отрезка (включительно)
  113. int right_border_id = i + (1 << j) - 1;
  114. //конец отрезка выходит за границу массива
  115. if (right_border_id + 1 > N) break;
  116. //середина отрезка
  117. int middle_id = i + (1 << (j - 1));
  118. //смотрим на 2 подотрезка:
  119. //(от начала до середины) и (от середины до конца)
  120. //buffer[i][j] = ...
  121. buffer[i].push_back(min(buffer[i][j - 1], buffer[middle_id][j - 1]));
  122. }
  123. }
  124. }
  125. //получить данные, хранящиеся в таблице
  126. const vector<vector<element>>& get_buffer() const {
  127. return buffer;
  128. }
  129. };
  130.  
  131. class RMQ {
  132. private:
  133. //бесконечность
  134. const int INF = 0x80000000 - 1;
  135. //Sparse Table
  136. const vector<vector<element>>& ST;;
  137. //логарифм по основанию 2 с округлением вниз
  138. //например log(10)=log(8)=3
  139. int log(const int val) const {
  140. if (val == 1) return 0;
  141. return log(val / 2) + 1;
  142. }
  143.  
  144. public:
  145. RMQ(int M, const sparce_table& _Table) : ST(_Table.get_buffer()) {}
  146. //минимум на отрезке с индексами от L до R включительно
  147. element find_min(const int L, const int R) const {
  148. assert(R >= L);
  149. //if (R == L) return ST[L][0];
  150. int j = log(R - L + 1);
  151. return min(ST[L][j], ST[R - (1 << j) + 1][j]);
  152. }
  153. int size() const { return ST.size(); }
  154. };
  155.  
  156. class Graph {
  157. private:
  158. int v_num;
  159. //список смежности
  160. vector<vector<int>> buffer;
  161. void add_edge(const int from, const int to) { buffer[from].push_back(to); }
  162. //ввод графа с потока
  163. friend void operator>>(istream& inp, Graph& G) {
  164. for (int i = 1; i < G.size(); i++) {
  165. int parent;
  166. inp >> parent;
  167. G.add_edge(parent, i);
  168. }
  169. }
  170. public:
  171. //создание и считывание графа
  172. Graph(int _v_num) : v_num(_v_num) {
  173. buffer.resize(v_num);
  174. cin >> *this;
  175. }
  176. int size() const { return v_num; }
  177. //обходим граф в глубину:
  178. //-попадая в вершину(в том числе и в корень)
  179. //--записываем ее в конец массива way(изначально пустого)
  180. //---мы записываем вершину в массив, даже возвращаясь в нее из рекурсии
  181. //--также, первый раз посетив вершину мы запоминаем
  182. //---под каким индексом она была записана в way
  183. void dfs(vector<int>& pos, vector<element>& way,
  184. const int cur_num, const int cur_depth) const {
  185. //первый раз посетили вершину
  186. //запоминаем ее
  187. way.push_back(element(cur_num, cur_depth));
  188. //и ее индекс
  189. pos[cur_num] = way.size() - 1;
  190. //рекурсивно запускаем dfs от детей
  191. for (auto _next: buffer[cur_num]){
  192. dfs(pos, way, _next, cur_depth + 1);
  193. //При каждом посещении вершины, записываем ее в way
  194. way.push_back(element(cur_num, cur_depth));
  195. }
  196.  
  197. }
  198. };
  199.  
  200. //поиск наименьшего общего предка 2 вершин(решение задачи)
  201. class LCA {
  202. private:
  203. //параметры для вычисления a3, a4 и т.д.
  204. long long x, y, z;
  205. //вершины, для которых ищут LCA
  206. long long a1, a2;
  207. //количество вершин в дереве
  208. long long N;
  209. //количество запросов
  210. int M;
  211. friend void operator>>(istream& inp, LCA& lca) {
  212. inp >> lca.a1 >> lca.a2;
  213. inp >> lca.x >> lca.y >> lca.z;
  214. }
  215. //найти следующую вершину для запроса
  216. //-например, найти a3, зная a1 и a2
  217. int next_v() const { return (a1 * x + a2 * y + z) % N; }
  218. //перейти к следующему запросу
  219. //-например, заменить a1 и a2 на a3 и a4
  220. void next_request() {
  221. //заменить a1 на a3
  222. a1 = next_v();
  223. //поменять местами a3 и a2
  224. swap(a1, a2);
  225. //заменить a2 на a4
  226. a1 = next_v();
  227. //поменять местами a4 и a3
  228. swap(a1, a2);
  229. }
  230. public:
  231. //решение задачи(конструктор)
  232. LCA(int _M, const Graph& G): M(_M), N(G.size()) {
  233. cin >> *this;
  234. //pos[i] - индекс (первого вхождения) вершины i в массиве way
  235. vector<int> pos(N, -1);
  236. //очередность обхода dfs-ом
  237. vector<element> way;
  238. G.dfs(pos, way, 0, 0);
  239. //помещаем 'хронологию' обхода в sapce table
  240. sparce_table table(way);
  241. //и готовимся искать минимум на выбранном участке
  242. RMQ rmq(M, table);
  243. //ans - ответ на предыдущий запрос
  244. //у самого первого запроса не было предыдущего, так что для него ans.num = 0
  245. element ans(0, -1);
  246. //сумма всех ответов на запросы(ответ на задачу)
  247. int s = 0;
  248. //для каждого из M запросов
  249. for (int i = 0; i < M; i++) {
  250. //выбираем участок 'хронологии' в зависимости от запроса
  251. int first_pos = pos[(a1 + ans.num) % N];
  252. int second_pos = pos[a2];
  253. //левый индекс должен быть меньше правого
  254. if (first_pos > second_pos) { swap(first_pos, second_pos); }
  255. //ищем минимум на интересующем нас участке
  256. ans = rmq.find_min(first_pos, second_pos);
  257. //прибавляем к сумме результат запроса
  258. s += ans.num;
  259. //генерируем следующий запрос
  260. next_request();
  261. }
  262. //вывод ответа
  263. cout << s;
  264.  
  265. }
  266. };
  267.  
  268. int main()
  269. {
  270. int N, M;
  271. cin >> N >> M;
  272. Graph G(N);
  273. LCA(M, G);
  274. system("pause");
  275. return 0;
  276. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement