Advertisement
MadCortez

Untitled

Mar 17th, 2021
402
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 5.08 KB | None | 0 0
  1. const
  2. sz=100000; //sz=maxN
  3.  
  4. var                                         // Дерево суммы
  5. b,ans:int64;                                // массив длины n
  6. i,n,t,q,st,fn,l_q,r_q,size:longint;         // q запросов
  7. l,r,ch1,ch2:array [1..4*sz] of longint;     // запрос вида "1 l_q r_q" - сумма на отрезке [l_q,r_q]
  8. push,tree:array [1..4*sz] of longint;       // запрос вида "2 l_q r_q b" - прибавить на отрезке [l_q,r_q] число  
  9.                                             // b ко всем элементам
  10. function min(a,b:longint):longint;
  11. begin
  12. if a<b then
  13.   min:=a
  14. else
  15.   min:=b;
  16. end;
  17.  
  18. function max(a,b:longint):longint;
  19. begin
  20. if a>b then
  21.   max:=a
  22. else
  23.   max:=b;
  24. end;
  25.  
  26. procedure build(i:longint); // рекурсия заполения дерева
  27. begin
  28. if l[i]=r[i] then // если лист - выходим
  29.   exit;
  30. build(ch1[i]); // запускае рекурсию
  31. build(ch2[i]); // от детей
  32. tree[i]:=tree[ch1[i]]+tree[ch2[i]]; // значение ячейки - сумма ячеек-детей
  33. end;
  34.  
  35. procedure find(i,l_q,r_q:longint); // рекурсия подсчета ответа
  36. begin
  37. if push[i]>0 then  // провеляем наличие обещаний
  38.   begin            // (push[i] - обещание на i-ую ячейку)
  39.   tree[i]:=tree[i]+push[i]*(r[i]-l[i]+1); // выполняем оббещание
  40.   if l[i]<>r[i] then
  41.     begin
  42.     push[ch1[i]]:=push[ch1[i]]+push[i]; // передаем обещания
  43.     push[ch2[i]]:=push[ch2[i]]+push[i]; // детям
  44.     end;
  45.   push[i]:=0; // выполнили обещания - обнуляем
  46.   end;
  47. if (l[i]=l_q) and (r[i]=r_q) then // если запрос соответствует отрезку ячейки
  48.   begin
  49.   ans:=ans+tree[i];               // добавляем сумму ячейки к ответу
  50.   exit;                           // выходим  
  51.   end;
  52. if l_q<=r[ch1[i]] then                 // проверяем, нужно ли спрашивать у левого сына
  53.   find(ch1[i],l_q,min(r_q,r[ch1[i]])); // спрашиваем у левого сына в нужных границах
  54. if r_q>=l[ch2[i]] then                 // проверяем, нужно ли спрашивать у правого сына
  55.   find(ch2[i],max(l_q,l[ch2[i]]),r_q); // спрашиваем у правого сына в нужных границах
  56. end;
  57.  
  58. procedure modify(i,l_q,r_q,b:longint); // рекурсия изменения дерева
  59. begin
  60. tree[i]:=tree[i]+b*(r_q-l_q+1);     // увеличиваем на длину отрезка отрезок
  61. if (l[i]=l_q) and (r[i]=r_q) then   // если запрос соответствует отрезку ячейки
  62.   begin
  63.   if l[i]<>r[i] then                // если не лист
  64.     begin
  65.     push[ch1[i]]:=push[ch1[i]]+b;   // даем обещания
  66.     push[ch2[i]]:=push[ch2[i]]+b;   // детям
  67.     end;
  68.   exit;
  69.   end;
  70. if l_q<=r[ch1[i]] then                     // проверяем, нужно ли изменять левого сына        
  71.   modify(ch1[i],l_q,min(r_q,r[ch1[i]]),b); // изменяем левого сына в нужных границах
  72. if r_q>=l[ch2[i]] then                     // проверяем, нужно ли изменять правого сына
  73.   modify(ch2[i],max(l_q,l[ch2[i]]),r_q,b); // изменяем правого сына в нужных границах
  74. end;
  75.  
  76.  
  77. begin
  78. readln(n,q);
  79. size:=1;
  80. while n>size do // вычисляем size - количество эллементов на последнем  
  81.   size:=size*2; // уровне дерева (добиаваем до степени двойки)
  82. l[1]:=1;        // границы первой ячейки
  83. r[1]:=size;
  84. fn:=1;
  85. st:=0;
  86. while true do   // запускаем цикл (можно бесконечный)
  87.   begin
  88.   inc(st);
  89.   if l[st]=r[st] then  // проверяем: если это лист - ввыходим из цикла
  90.     break;
  91.   inc(fn); // создаем левого сына
  92.   ch1[st]:=fn;
  93.   l[fn]:=l[st];
  94.   r[fn]:=(l[st]+r[st]) div 2;
  95.   inc(fn); // создаем правого сына
  96.   ch2[st]:=fn;
  97.   l[fn]:=r[fn-1]+1;
  98.   r[fn]:=r[st];
  99.   end;
  100. for i:=1 to n do
  101.   begin
  102.   read(tree[st]); // зачитываем массив
  103.   inc(st);        // на последний уровень дерева
  104.   end;
  105. build(1);         // запускаем рекурсию заполнения дерева
  106. for i:=1 to q do  // начинаем обрабатывать запросы
  107.   begin
  108.   read(t,l_q,r_q);
  109.   if t=1 then  // запрос суммы
  110.     begin
  111.     ans:=0;    // обнуляем ответ
  112.     find(1,l_q,r_q); // запускаем рекурсию подсчета ответа
  113.     writeln(ans);
  114.     continue;
  115.     end;
  116.   if t=2 then  // запрос изменения
  117.     begin
  118.     read(b);
  119.     modify(1,l_q,r_q,b);  // запускаем рекурсию изменения дерева
  120.     continue;
  121.     end;
  122.   end;
  123. end.
  124.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement