Однажды детектив
Сайкат расследовал дело об убийстве. На месте преступления он обнаружил
лестницу, на каждой ступеньке которой было написано число. Детектив счел это
подозрительным и решил запомнить все числа, встреченные на пути. Вскоре он
заметил закономерность: для каждого числа на лестнице он записывал сумму всех
ранее встреченных чисел, которые были меньше текущего.
Вам необходимо
найти сумму всех чисел, записанных детективом в его дневнике.
Вход. Первая строка содержит число t (t ≤ 10) – количество тестов. Далее следуют 2t строк. В первой из
них указано число n (1 ≤ n ≤ 105) – количество ступенек. В
следующей строке записаны n чисел – значения, нанесенные на ступеньки.
Все числа находятся в диапазоне от 0 до 106.
Выход. Для каждого теста выведите
в отдельной строке итоговую сумму.
Пример входа |
Пример выхода |
1 5 1 5 3 6 4 |
15 |
структуры
данных – дерево Фенвика
Числа,
записанные на ступеньках, являются целыми и находятся в диапазоне от 0 до 106
включительно. Построим дерево Фенвика на массиве a длины 106
+ 1 (индексы массива
изменяются от 0 до 106 включительно), изначально заполненном нулями.
Каждый раз,
когда детектив проходит ступеньку со значением value, увеличим avalue
на value. При этом в дневнике он запишет сумму:
a0 + a1
+ a2 + … + avalue-1
С учетом ограничений на
входные данные, все вычисления следует выполнять в 64-битовом целочисленном
типе.
Пример
Смоделируем записи
детектива на приведённом примере. Индексация массива начинается с 0. Числа,
записанные детективом, указаны под стрелками.
Сумма чисел,
записанных в дневнике детектива, равна
0 + 1 + 1 + 9 +
4 = 15
Пусть максимальный размер
массива равен MAX. Создадим дерево Фенвика Fenwick.
#define MAX 1000001
vector<long
long> Fenwick;
Функция Summa0_i вычисляет значение суммы a0 + a1
+ ... + ai.
long long
Summma0_i(int i)
{
long long result = 0;
for (; i
>= 0; i = (i & (i + 1)) - 1)
result += Fenwick[i];
return
result;
}
Функция IncElement увеличивает значение элемента: ai = ai
+ delta.
void IncElement(int
i, int delta)
{
for (; i <
MAX; i = (i | (i+1)))
Fenwick[i] += delta;
}
Основная часть программы. Читаем входные данные.
scanf("%d",&tests);
while
(tests--)
{
scanf("%d",&n);
Заполняем массив Fenwick
нулями.
Fenwick.assign(MAX,0);
Искомую сумму, записанную в дневнике детектива, будем подсчитывать
в переменной sum.
sum = 0;
Последовательно
обрабатываем числа, записанные на ступеньках.
for (i = 0; i
< n; i++)
{
Для
каждого значения value, записанного
на ступеньке, увеличиваем avalue на value, а также вычисляем сумму всех ранее
встреченных чисел, меньших value. Эта сумма
равна a0 + a1
+ a2 + … + avalue-1.
scanf("%d",&value);
IncElement(value, value);
sum += Summma0_i(value - 1);
}
Выводим сумму
всех чисел, записанных в дневнике детектива.
printf("%lld\n",sum);
}