Pilləkən Qaydaları#4073

Pilləkən Qaydaları (Həll təhlili)

Pilləkənlər üzərində yazılmış ədədlər tam ədədlərdir və -dan 10^6-ya kimi (daxil olmaqla) aralıqdadır. 10^6 + 1 uzunluğunda sıfırlarla doldurulmuş massivində Fenwick ağacını quracağıq (massivin indeksləri -dan 10^6-ya kimi dəyişir).

Hər dəfə dedektiv dəyəri olan bir pilləkəndən keçəndə, a_{value}-ı qədər artıracağıq. Həmin vaxt gündəlikdə o, məbləğini yazacaq:

a_0 + a_1 + a_2 + ... + a_{value - 1}

Giriş verilənlərinin məhdudiyyətlərini nəzərə alaraq, bütün hesablamaları bitlik tam ədəd tipində yerinə yetirmək lazımdır.

Məsələnin nümunəsi

Verilmiş nümunəni istifadə edərək dedektivin yazılarını simulyasiya edək. Massivin indeksləşdirilməsi -dan başlayır. Dedektiv tərəfindən yazılmış ədədlər oxların altında yerləşdirilib.

Dedektivin gündəliyində yazılmış ədədlərin cəmi bərabərdir:

0 + 1 + 1 + 9 + 4 = 15

Alqoritmin realizasiyası

Qoy massivin maksimal ölçüsü olsun. Fenwick ağacını yaradaq.

#define MAX 1000001
vector<long long> Fenwick;

Summa0_i funksiyası a_0 + a_1 + ... + a_i cəm məbləğini hesablayır.

long long Summma0_i(int i)
{
  long long result = 0;
  for (; i >= 0; i = (i & (i + 1)) - 1)
    result += Fenwick[i];
  return result;
}

IncElement funksiyası elementi artırır: a_i = a_i + delta.

void IncElement(int i, int delta)
{
  for (; i < MAX; i = (i | (i+1)))
    Fenwick[i] += delta;
}

Proqramın əsas hissəsi. Giriş verilənlərini oxuyuruq.

scanf("%d",&tests);
while (tests--)
{
  scanf("%d",&n);

Fenwick massivini sıfırlarla doldururuq.

  Fenwick.assign(MAX,0);

Dedektivin gündəliyində yazılmış olan nəticəni dəyişənində hesablayacağıq.

  sum = 0;

Pilləkənlər üzərində yazılmış ədədləri ardıcıl emal edirik.

  for (i = 0; i < n; i++)
  {

Hər pilləkən üzərinə yazılmış dəyəri üçün, a_{value}-ı -a artırırıq, həmçinin -dan kiçik olan daha əvvəl görülmüş bütün ədədlərin cəmini hesablayırıq. Bu cəm a_0 + a_1 + a_2 + ... + a_{value - 1}-ə bərabərdir.

    scanf("%d",&value);
    IncElement(value, value);
    sum += Summma0_i(value - 1);
  }

Dedektivin gündəliyində yazılmış bütün ədədlərin cəmini çıxarıq.

  printf("%lld\n",sum);
}