4496.
Приключение Незнайки и его друзей
Все мы помним
историю о том, как Незнайка со своими друзьями летали на воздушном шаре
путешествовать. Но не все знают, что не все человечки влезли в шар, так как у
него была ограниченная грузоподъемность.
В этой задаче
Вам необходимо узнать, сколько же человечков улетело путешествовать. Известно,
что посадка в шар не является оптимальной, а именно: человечки садятся в шар в
той очереди, в которой они стоят, как только кому-то из них не хватает места,
он и все оставшиеся в очереди разворачиваются и уходят домой.
Вход. В первой строке содержится количество человечков n (1 ≤ n ≤ 106) в цветочном городе. Во второй строке
заданы веса каждого из человечков в том порядке, в котором они будут садиться в
шар. Все веса натуральные числа и не превышают 109. Далее следует
количество запросов m (1 ≤ m ≤ 105). Каждый запрос
представляет собой одну строку. Первое число t в строке – тип запроса.
·
Если t = 1, то далее следует еще одно число v (1 ≤ v
≤ 109) – грузоподъемность воздушного шара.
·
Если t = 2, то далее следует два числа x (1 ≤ x ≤ n) и y (1 ≤ y ≤ 109) – вес человечка на позиции x становится равным y.
Выход. Для каждого запроса с номером один
выведите в отдельной строке количество человечков, поместившихся в шар.
Пример
входа |
Пример
выхода |
5 1 2 3 4 5 5 1 7 1 3 2 1 5 1 7 1 3 |
3 2 2 0 |
структуры данных - дерево отрезков,
единичная модификация
Для решения
задачи следует реализовать дерево отрезков, поддерживающее сумму элементов, модификацию
единичного элемента (первое число запроса равно двум) и вычисление
специфической функции (количество человечков, которое поместится в воздушный
шар).
Если первое
число в запросе равно единице, то необходимо найти количество последовательных
элементов (начиная с первого), сумма которых не превышает грузоподъемность
воздушного шара v.
Объявим массив SegTree для хранения
дерева отрезков. Входную последовательность чисел храним в массиве m. Дерево
отрезков поддерживает операцию суммы. Веса человечков не больше 109, всего человечков не более 106, следовательно суммы на отрезках (значения в ячейках SegTree) не будут выходить за границу 64
битового целочисленного типа.
vector<long long> SegTree;
vector<int> m;
Функция Buildtree по массиву m строит дерево
отрезков, поддерживающее сумму.
void BuildTree(int v, int lpos, int rpos)
{
if (lpos == rpos) SegTree[v] = m[lpos];
else
{
int mid = (lpos + rpos) / 2;
BuildTree(2 * v, lpos, mid);
BuildTree(2 * v + 1, mid + 1, rpos);
SegTree[v] = SegTree[2 * v] + SegTree[2 * v + 1];
}
}
Функция Get возвращает количество последовательных элементов (начиная с
первого), сумма которых не превышает грузоподъемность воздушного шара w.
int Get(int v, int lpos, int rpos, long long w)
{
Если отрезок [lpos; rpos] состоит из одного элемента, то
ответ равен 1, если человечка с весом SegTree[v] можно поместить в шар, и 0 иначе.
if (lpos == rpos) return SegTree[v] <= w;
Находим середину отрезка mid =
(lpos + rpos) / 2.
int mid = (lpos + rpos) / 2;
Если сумма весов SegTree[2*v] человечков в левом поддереве дерева
отрезков больше w, то все человечки из левого поддерева не войдут в воздушный
шар. Поэтому ответ следует искать только в левом поддереве.
if (SegTree[2 * v] > w)
return Get(2 * v, lpos, mid, w);
else
Иначе в шар следует посадить всех
человечков из левого поддерева (их количество
равно mid – lpos + 1 с общим весом SegTree[2*v]), а также человечков из правого поддерева начиная с позиции mid + 1 и далее пока общая сумма
весов человечков из правого поддерева не станет больше w – SegTree[2*v].
return mid - lpos + 1 +
Get(2 * v + 1, mid + 1, rpos, w -
SegTree[2 * v]);
}
Функция Update в позицию pos записывает значение val. Вершине v соответствует отрезок [lpos, rpos].
void Update(int v, int lpos, int rpos, int pos, int val)
{
if (lpos == rpos) SegTree[v] = val;
else
{
int mid = (lpos + rpos) / 2;
if (pos <=
mid) Update(v * 2, lpos, mid, pos, val);
else Update(v * 2 +
1, mid + 1, rpos, pos, val);
SegTree[v] = SegTree[2 * v] + SegTree[2 * v + 1];
}
}
Основная часть
программы. Читаем входную последовательность чисел в массив m, начиная с
первого индекса.
scanf("%d", &n);
SegTree.resize(4 * n
+ 10);
m.resize(n + 1);
for (i = 1; i <= n; i++) scanf("%d", &m[i]);
Строим дерево отрезков по элементам
массива m[1..n].
BuildTree(1,1,n);
Последовательно обрабатываем запросы.
scanf("%d",&q);
for(i = 0; i < q; i++)
{
scanf("%d",&op);
if (op == 1)
{
scanf("%d",&Weight);
printf("%d\n",Get(1,1,n,Weight));
} else
{
scanf("%d
%d",&x,&y);
Update(1,1,n,x,y);
}
}