С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/26: Рейтинг темы: голосов - 26, средняя оценка - 4.73
 Аватар для shPavel25
6 / 6 / 0
Регистрация: 29.03.2011
Сообщений: 47

Дерево отрезков

30.07.2012, 21:00. Показов 5700. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, помогите пож-та решить задачи на с++. Нашел решение (расписаны все алгоритмы, процедуры подсчета и т. д.), но сложность состоит в том, что я не понимаю строищихся структур и вообще никогда не программировал на c++.Поэтому прошу помочь собрать все воедино (чтение из файла, работа программы, запись в файл). Основная задача - считать с файла, воспользоваться функцией, вывести в файл

Дан массив целых чисел. Поступают запросы модификации элемента и поиска суммы элементов на отрезке. Необходимо ответить на каждый запрос суммы.
Вход:
В первой строке через пробел записаны два натуральных числа N и M (N, M < 105), где N – количество элементов массива, M – количество запросов. Во второй строке записан массив чисел (элементы массива разделены пробелом). В следующих M строках идут запросы (по одному в строке). Запрос вида 'M 5 9' означает, что необходимо присвоить элементу с индексом 5 число 9. Запрос вида 'S 2 4' означает, что необходимо найти сумму элементов массива, начиная от элемента с индексом
2 и заканчивая элементом с индексом 4 (включая эти два элемента). Гарантируется, что второй индекс больше первого. Гарантируется, что массив имеет элементы с такими индексами. Все элементы в массиве до и после замены – неотрицательные целые числа меньше 10.
Индексация элементов массива идет с нуля.
Выход:
Для каждого запроса поиска суммы выведите результат его выполнения в порядке появления (каждый на отдельной строке)
.***решение

Построим бинарное дерево T следующим образом. Корень дерева будет храниться в элементе T[1]. Он
будет содержать сумму элементов A[0..N-1], т.е. всего массива. Левый сын корня будет храниться в элементе T[2] и содержать сумму первой половины массива A: A[0..N/2], а правый сын - в элементе T[3] и содержать сумму элементов A[N/2+1..N-1]. В общем случае, если T[i]-ый элемент содержит сумму элементов с L-го по R-ый, то его левым сыном будет элемент T[i*2] и содержать сумму A[L..(L+R)/2], а его правым сыном будет T[i*2+1] и содержать сумму A[(L+R)/2+1..R]. Исключение, разумеется, составляют листья дерева - вершины, в которых L = R.

Рассмотрим теперь операцию суммы на некотором отрезке [L; R]. Мы встаём в корень дерева (i=1), и
рекурсивно движемся вниз по этому дереву. Если в какой-то момент оказывается, что L и R совпадают с границами отрезка текущего элемента, то мы просто возвращаем значение текущего элемента T. Иначе, если отрезок [L; R] целиком попадает в отрезок левого или правого сына текущего элемента, то мы рекурсивно вызываем себя из этого сына и найденное значение возвращаем. Наконец, если отрезок [L; R] частично принадлежит и отрезку левого сына, и отрезку правого сына, то делим отрезок [L; R] на два отрезка [L; M] и [M+1; R] так, чтобы первый отрезок целиком принадлежал отрезку левого сына, а второй отрезок - отрезку правого сына, и рекурсивно вызываем себя и от первого, и от второго отрезков, возвращая сумму найденных сумм.
Теперь рассмотрим операцию изменения значения некоторого элемента с индексом K. Будем спускаться по дереву от корня, ища тот лист, который содержит значение элемента A[K]. Когда мы найдём этот элемент, просто изменим соответствующее значение в массиве T и будем подниматься от текущего элемента обратно к корню, пересчитывая текущие значения T. Понятно, что таким образом мы изменим все значения в дереве, которые нужно изменить.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
vector<long long> t;
int n;
void build (const vector<int> & a, int i = 1, int l = 0, int r = n-1) {
if (i == 1)
t.resize (n*4 + 1);
if (l == r)
t[i] = a[l];
else {
int m = (l + r) / 2;
build (a, i*2, l, m);
build (a, i*2+1, m+1, r);
t[i] = t[i*2] + t[i*2+1];
}
}
long long sum (int l, int r, int i = 1, int tl = 0, int tr = n-1) {
if (l == tl && r == tr)
return t[i];
int m = (tl + tr) / 2;
if (r <= m)
return sum (l, r, i*2, tl, m);
if (l > m)
return sum (l, r, i*2+1, m+1, tr);
return sum (l, m, i*2, tl, m) + sum (m+1, r, i*2+1, m+1, tr);
}
void update (int pos, int newval, int i = 1, int l = 0, int r = n-1) {
if (l == r)
t[i] = newval;
else {
int m = (l + r) / 2;
if (pos <= m)
update (pos, newval, i*2, l, m);
else
update (pos, newval, i*2+1, m+1, r);
t[i] = t[i*2] + t[i*2+1];
}
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
30.07.2012, 21:00
Ответы с готовыми решениями:

Медленное дерево отрезков
Приветствую. Пишу дерево отрезков для задачи нахождения сумм на отрезках. Оно работает, даже вроде правильно, но при массиве 105 и...

Дерево отрезков, проверьте код
реализовал дерево отрезков, хотелось бы знать можно ли его как-нибудь улучшить, исправить. интересует вопрос: как вызвать конструктор...

Дерево отрезков, редактирование куска и поиск суммы
Добрый вечер. Пишу алгоритм нахождения суммы элементов на отрезке и редактирования элементов на отрезке. Вводится N - число элементов в...

4
14 / 14 / 3
Регистрация: 28.07.2012
Сообщений: 57
31.07.2012, 00:07
Опять списал с емакса... Там дерево отрезков нормально объяснено.
0
 Аватар для shPavel25
6 / 6 / 0
Регистрация: 29.03.2011
Сообщений: 47
31.07.2012, 00:09  [ТС]
я не спорю, все хорошо объяснено, мне не совсем понятно как считывать с файла и закидывать в функцию, какая структура данных должна быть
0
14 / 14 / 3
Регистрация: 28.07.2012
Сообщений: 57
31.07.2012, 00:16
C++
1
2
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
связывание с файлом. Затем используя потоки cin, cout ввод-вывод. в Дейкстре есть и ввод и вывод. он аналогичен для всех типов данных. Структура данных написана уже (массив, хранящий двоичное дерево)
0
 Аватар для shPavel25
6 / 6 / 0
Регистрация: 29.03.2011
Сообщений: 47
31.07.2012, 01:23  [ТС]
то есть если напишу так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
 
vector<long long> t;
int n;
void build (const vector<int> & a, int i = 1, int l = 0, int r = n-1) {
if (i == 1)
t.resize (n*4 + 1);
if (l == r)
t[i] = a[l];
else {
int m = (l + r) / 2;
build (a, i*2, l, m);
build (a, i*2+1, m+1, r);
t[i] = t[i*2] + t[i*2+1];
}
}
long long sum (int l, int r, int i = 1, int tl = 0, int tr = n-1) {
if (l == tl && r == tr)
return t[i];
int m = (tl + tr) / 2;
if (r <= m)
return sum (l, r, i*2, tl, m);
if (l > m)
return sum (l, r, i*2+1, m+1, tr);
return sum (l, m, i*2, tl, m) + sum (m+1, r, i*2+1, m+1, tr);
}
void update (int pos, int newval, int i = 1, int l = 0, int r = n-1) {
if (l == r)
t[i] = newval;
else {
int m = (l + r) / 2;
if (pos <= m)
update (pos, newval, i*2, l, m);
else
update (pos, newval, i*2+1, m+1, r);
t[i] = t[i*2] + t[i*2+1];
}
}
int main()
{
    freopen("input.txt","r",stdin); 
    freopen("output.txt","w",stdout);
int n,m;
cin>>n>>m;
 vector<int> a(n);
  for (int i = 0; i <n; i++)
         cin>>a[i];
//я так понимаю теперь строим T
build (a);
//по задаче подается m запросов - если S 2 4  - сумма со 2 по 4 элемента включительно
// М 5 9  - необходимо присвоить элементу 5 значение 9
char operation;
int q1,q2;
for (i=0; i<m; ++i)
{
cin>>operation>>q1>>q2;
if (operation="S") 
sum(q1,q2);
else 
update(q1,q2);
}
for (i=0; i<m; ++i)
cout<<t[i]<<'" ";
}
или я не правильно понял?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
31.07.2012, 01:23
Помогаю со студенческими работами здесь

На прямой своими концами заданы N отрезков. Найти точку принадлежащую максимальному числу отрезков
Помогите пожалуйста понять, что от меня хотят и какой(как) разработать алгоритм для решения этой задачи. На прямой своими концами...

Дерево отрезков. Поиск суммы чисел на отрезке массива. Изменение всех чисел на отрезке массива
Добрый день, помогите пож-та решить задачу на с++.И если возможно ,то с объяснением.

Есть ли у кого похожий алгоритм: распределения отрезков разной длины внутри отрезков фиксированной длины?
Народ помогите мне с программой распределения отрезков разной длины внутри отрезков фиксированной длины с минимальными остатками. К...

Бинарное дерево. Удалить из дерева часть вершин так, чтобы оставшееся дерево стало пирамидой
Дано бинарное дерево. Удалить из дерева часть вершин так, чтобы оставшееся дерево стало пирамидой.

Дано дерево. Распечатать дерево по уровням
Дано дерево. Распечатать дерево по уровням.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru