Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const
- sz=100000; //sz=maxN
- var // Дерево суммы
- b,ans:int64; // массив длины n
- i,n,t,q,st,fn,l_q,r_q,size:longint; // q запросов
- l,r,ch1,ch2:array [1..4*sz] of longint; // запрос вида "1 l_q r_q" - сумма на отрезке [l_q,r_q]
- push,tree:array [1..4*sz] of longint; // запрос вида "2 l_q r_q b" - прибавить на отрезке [l_q,r_q] число
- // b ко всем элементам
- function min(a,b:longint):longint;
- begin
- if a<b then
- min:=a
- else
- min:=b;
- end;
- function max(a,b:longint):longint;
- begin
- if a>b then
- max:=a
- else
- max:=b;
- end;
- procedure build(i:longint); // рекурсия заполения дерева
- begin
- if l[i]=r[i] then // если лист - выходим
- exit;
- build(ch1[i]); // запускае рекурсию
- build(ch2[i]); // от детей
- tree[i]:=tree[ch1[i]]+tree[ch2[i]]; // значение ячейки - сумма ячеек-детей
- end;
- procedure find(i,l_q,r_q:longint); // рекурсия подсчета ответа
- begin
- if push[i]>0 then // провеляем наличие обещаний
- begin // (push[i] - обещание на i-ую ячейку)
- tree[i]:=tree[i]+push[i]*(r[i]-l[i]+1); // выполняем оббещание
- if l[i]<>r[i] then
- begin
- push[ch1[i]]:=push[ch1[i]]+push[i]; // передаем обещания
- push[ch2[i]]:=push[ch2[i]]+push[i]; // детям
- end;
- push[i]:=0; // выполнили обещания - обнуляем
- end;
- if (l[i]=l_q) and (r[i]=r_q) then // если запрос соответствует отрезку ячейки
- begin
- ans:=ans+tree[i]; // добавляем сумму ячейки к ответу
- exit; // выходим
- end;
- if l_q<=r[ch1[i]] then // проверяем, нужно ли спрашивать у левого сына
- find(ch1[i],l_q,min(r_q,r[ch1[i]])); // спрашиваем у левого сына в нужных границах
- if r_q>=l[ch2[i]] then // проверяем, нужно ли спрашивать у правого сына
- find(ch2[i],max(l_q,l[ch2[i]]),r_q); // спрашиваем у правого сына в нужных границах
- end;
- procedure modify(i,l_q,r_q,b:longint); // рекурсия изменения дерева
- begin
- tree[i]:=tree[i]+b*(r_q-l_q+1); // увеличиваем на длину отрезка отрезок
- if (l[i]=l_q) and (r[i]=r_q) then // если запрос соответствует отрезку ячейки
- begin
- if l[i]<>r[i] then // если не лист
- begin
- push[ch1[i]]:=push[ch1[i]]+b; // даем обещания
- push[ch2[i]]:=push[ch2[i]]+b; // детям
- end;
- exit;
- end;
- if l_q<=r[ch1[i]] then // проверяем, нужно ли изменять левого сына
- modify(ch1[i],l_q,min(r_q,r[ch1[i]]),b); // изменяем левого сына в нужных границах
- if r_q>=l[ch2[i]] then // проверяем, нужно ли изменять правого сына
- modify(ch2[i],max(l_q,l[ch2[i]]),r_q,b); // изменяем правого сына в нужных границах
- end;
- begin
- readln(n,q);
- size:=1;
- while n>size do // вычисляем size - количество эллементов на последнем
- size:=size*2; // уровне дерева (добиаваем до степени двойки)
- l[1]:=1; // границы первой ячейки
- r[1]:=size;
- fn:=1;
- st:=0;
- while true do // запускаем цикл (можно бесконечный)
- begin
- inc(st);
- if l[st]=r[st] then // проверяем: если это лист - ввыходим из цикла
- break;
- inc(fn); // создаем левого сына
- ch1[st]:=fn;
- l[fn]:=l[st];
- r[fn]:=(l[st]+r[st]) div 2;
- inc(fn); // создаем правого сына
- ch2[st]:=fn;
- l[fn]:=r[fn-1]+1;
- r[fn]:=r[st];
- end;
- for i:=1 to n do
- begin
- read(tree[st]); // зачитываем массив
- inc(st); // на последний уровень дерева
- end;
- build(1); // запускаем рекурсию заполнения дерева
- for i:=1 to q do // начинаем обрабатывать запросы
- begin
- read(t,l_q,r_q);
- if t=1 then // запрос суммы
- begin
- ans:=0; // обнуляем ответ
- find(1,l_q,r_q); // запускаем рекурсию подсчета ответа
- writeln(ans);
- continue;
- end;
- if t=2 then // запрос изменения
- begin
- read(b);
- modify(1,l_q,r_q,b); // запускаем рекурсию изменения дерева
- continue;
- end;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement