Basecamp
    Ana Səhifə
    Problemlər
    Müsabiqələr
    Kurslar
    Reytinq
    Postlar
    Mağaza
    Discord
İki göstərici texnikası
Daxil ol
medv
•Article•11 ay öncə

İki göstərici texnikası

İki göstərici texnikası, kompüter elmləri və proqramlaşdırmada, massivlər və ya ardıcıllıqlar ilə bağlı problemlərin həlli üçün geniş istifadə olunan bir strategiyadır. Bu, massiv və ya ardıcıllığı müxtəlif mövqelərdən keçən iki göstəricinin istifadəsini əhatə edir, tez-tez əks istiqamətlərdə və ya fərqli sürətlə hərəkət edirlər. Bu texnika, axtarış, optimallaşdırma və ya massivlərin səmərəli şəkildə manipulyasiyası ilə bağlı problemlərin həllində xüsusilə faydalıdır.

İki göstərici texnikasının necə işlədiyinə dair bir qısa izah:

  • Başlanğıc: İlk olaraq, iki göstərici, adətən, massiv və ya ardıcıllığın müxtəlif mövqelərində yerləşdirirsiniz.

  • Hərəkət: Göstəriciləri müəyyən şərtlərə əsasən iterativ olaraq hərəkət etdirirsiniz, ta ki, onlar görüşənə qədər və ya müəyyən bir şərtə çatana qədər. Göstəricilərin hərəkəti problem tələblərinə əsasən idarə oluna bilər. Məsələn, bir göstərici digərlərinə nisbətən daha sürətlə hərəkət edə bilər, ya da onlar əks istiqamətlərdə hərəkət edə bilərlər.

  • Şərtin yoxlanması: Hər iterasiya addımında, problem tələblərinə əsaslanan müəyyən şərtləri yoxlayırsınız. Bu şərtlər tez-tez göstəriciləri hərəkət etdirmək, bəzi dəyişənləri yeniləmək və ya digər əməliyyatları həyata keçirmək üçün qərar verir.

  • Tamamlanma: Bu proses, bir və ya iki göstərici massiv və ya ardıcıllığın sonuna çatana qədər davam edir, ya da başqa bir tamamlanma şərti yerinə yetirilənə qədər davam edir.

İki göstərici texnikası, xüsusi meyarlara uyğun olan cütləri və ya alt massivləri axtarma, optimal həll yollarını tapma və ya ardıcıllıqları səmərəli şəkildə manipulyasiya etməklə bağlı problemlərdə xüsusilə faydalıdır, iç içə döngələrdən istifadə etmədən. Bu, xeyli vaxt sərf etmədən, düz xətti və ya logaritmik zaman mürəkkəblik tələbləri olan problemlər üçün genellikle daha səmərəli bir həll təqdim edir.

Eolymp #2098. İnvertor

n tam ədəd verilib. Onları tərs qaydada çap edin.

Giriş. Əvvəlcə n (0<n<100) verilmişdir, sonra n tam ədəd verilir.

Çıxış. Verilmiş n tam ədədi tərs qaydada çap edin.

Nümunə giriş
7
2 4 1 3 5 3 1
Nümunə çıxış
1 3 5 3 1 4 2
Problemi açıq
Həll

Rəqəmləri xətti massivdə saxlayın. Sonra onları tərs qaydada çap edin.

İki göstərici texnikası ilə massivini tərs çevirmək üçün bir həll düşünək.

İki dəyişəni i və j (onları göstəricilər adlandıracağıq) təyin edin:

  • i massivinin əvvəlində (i=1);

  • j massivinin sonunda (j=n);

Sonra bir while döngüsü başlayın, burada:

  • m[i] və m[j] dəyərləri dəyişdirilir;

  • sonra i 1 artırılır, j isə 1 azaldılır;

Göstəricilər i və j görüşənə qədər döngünü davam etdirin.

Qeyd edək ki, m[i] və m[j] dəyərlərini əlavə bir dəyişən temp ilə dəyişdirmək üçün üç əməliyyat aparılır:

Alqoritmin həyata keçirilməsi

Bir massiv elan edin.

#define MAX 110
int m[MAX];

Giriş məlumatlarını oxuyun.

scanf("%d",&n);
for(i = 1; i <= n; i++)
  scanf("%d",&m[i]);

İki göstərici ilə massivini tərs çevirin.

i = 1; j = n;
while(i < j)
{
  temp = m[i]; m[i] = m[j]; m[j] = temp;
  i++; j--;
}

Rəqəmləri çap edin.

for(i = 1; i <= n; i++)
  printf("%d ",m[i]);
printf("\n");
Eolymp #11387. Kart oyunları

Hüseyn və Yaroslav bir kart oyunu oynayır. Masanın üstündə ardıcıl düzülmüş n kart var, hər birinin üzərində fərqli bir rəqəm yazılıb. Oyunçular növbə ilə oynayırlar. Hüseyn oyuna başlayır. Hər dövrdə oyunçu ya sol kənar, ya da sağ kənar kartı ala bilər. Oyunçu həmişə ən yüksək rəqəmi olan kartı seçəcək. Oyun, masada kart qalmadıqda sona çatır. Oyun sonunda Hüseyn və Yaroslavın topladığı kartların rəqəmlərinin cəmini tapın.

Giriş. İlk sətirdə masada n (1≤n≤10000) kartın sayı var. İkinci sətirdə n müsbət tam ədəd var, hər biri kartın üzərindəki rəqəmi göstərir. Bütün ədədlər 109-dan böyük deyil.

Çıxış. Oyun sonunda Hüseyn və Yaroslavın topladığı kartların rəqəmlərinin cəmini çap edin.

Nümunə giriş
7
4 7 5 1 12 8 2
Nümunə çıxış
18 21
Problemi açıq
Həll

Gəlin m massivində kartların üzərindəki ədədləri saxlayaraq düşünək. Göstəricilər i=0 massivinin əvvəlində və j=n−1 massivinin sonunda başlayır.

Hər dövrdə, oyunçu maksimum dəyəri max(m[i],m[j]) olan kartı götürür, bundan sonra kart masadan çıxarılır (əgər m[i] kartı seçilirsə, i++ əməlini yerinə yetirin, m[j] kartı seçilirsə, j−− əməlini yerinə yetirin). Hər bir oyunçu seçilən kartların cəmini iki dəyişəndə saxlayır. Proses, bütün kartlar masadan çıxarılana qədər davam edir, yəni göstəricilər i və j görüşənə qədər.

Nümunə

Oyun aşağıdakı kimi davam edəcək.

Alqoritmin həyata keçirilməsi

Massivləri elan edin. Hüseyn və Yaroslavın topladığı kartların sayı res[0] və res[1]-də saxlanılacaq.

int m[10001], res[2];

Giriş məlumatlarını oxuyun.

scanf("%d", &n);
for (i = 0; i < n; i++)
  scanf("%d", &m[i]);

Göstəriciləri i=0 və j=n−1 təyin edin.

i = 0; j = n - 1;

Oyunçular növbə ilə, toplam n addım atırlar. Hüseyn cüt k üçün növbəyə girir, Yaroslav isə tək k üçün. Buna görə, Hüseynin cəmi res[0]-da, Yaroslavın cəmi isə res[1]-də toplanacaq.

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

Hər dövrdə, oyunçu maksimum dəyəri max(m[i],m[j]) olan kartı seçir.

  if (m[i] > m[j])
    res[k % 2] += m[i++];
  else
    res[k % 2] += m[j--]; ;
}

Cavabı çap edin.

printf("%d %d\n", res[0], res[1]);
Eolymp #11388. Kart oyunları 2

Hüseyn n kartı bir sıra düzülərək a1​,a2​,a3​,...,an​ ilə düzür. Sonra onları toplayır və başqa bir ardıcıllıqla düzür: a1​,a3​,a5​,...,a6​,a4​,a2​. Bu, Yaroslava verdiyi ardıcıllıqdır. Sizin işiniz, Yaroslavanın Hüseynin orijinal ardıcıllığını bərpa etməsinə kömək etməkdir.

Məsələn, əgər Yaroslava ardıcıllığı (2,4,9,4,7,6) verilibsə, o zaman o, Hüseyinə (2,6,4,7,9,4) ardıcıllığını qaytarmalıdır.

Giriş. İlk sətirdə bir tam ədəd n (1≤n≤10000) var, kartların sayı. İkinci sətirdə n müsbət tam ədəd var, kartların üzərindəki ədədlər. Bütün ədədlər 109-dan böyük deyil.

Çıxış. Hüseynin orijinal ardıcıllığını çap edin.

Nümunə giriş 1
6
2 4 9 4 7 6
Nümunə çıxış 1
2 6 4 7 9 4
Nümunə giriş 2
7
5 7 34 1 89 4 2
Nümunə çıxış 2
5 2 7 4 34 89 1
Problemi açıq
Həll

Gəlin a massivində kartların üzərindəki ədədləri saxlayaraq düşünək. İki göstəricini i=0 massivinin əvvəlində və j=n−1 massivinin sonunda təyin edin.

Orijinal ardıcıllığı bərpa etmək üçün, bütün elementlər işlənənə qədər soldan və sağdan kartları növbə ilə alın. Hər seçki ilə müvafiq göstərici öz mövqeyini dəyişir: i sağa, j isə sola hərəkət edir.

Nümunə

Gəlin bir neçə addımı ilk test nümunəsindən istifadə edərək araşdıraq.

Alqoritmin həyata keçirilməsi

Bir massiv elan edin.

int a[100001];

Giriş məlumatlarını oxuyun.

scanf("%d", &n);
for (i = 0; i < n; i++)
  scanf("%d", &a[i]);

Göstəriciləri i=0 və j=n−1 təyin edin.

i = 0; j = n - 1;

i≤j bərabərsizliyi mövcud olduqda, növbə ilə ai​ və aj​-ı çap edin, eyni zamanda göstəriciləri hərəkət etdirin.

while (i <= j)
{
  printf("%d ", a[i++]);
  if (i > j) break;
  printf("%d ", a[j--]);
}
Eolymp #11389. Hüseynin oyunu

Hüseynin 0 və 1 simvollarından ibarət bir stringi var. Özünü əyləndirmək üçün, o aşağıdakı oyunu düzəldib. Hüseyn stringə iki əməliyyatdan birini həyata keçirə bilər:

  • Sol ucuna 0, sağ ucuna 1 əlavə etmək;

  • Sağ ucuna 0, sol ucuna 1 əlavə etmək;

Məsələn, 010 stringindən Hüseyn 00101 və ya 10100 ala bilər.

Siz, Hüseyinin bütün əməliyyatlardan sonra əldə etdiyi stringi verirsiniz (ola bilsin ki, o, heç bir əməliyyat etməyib). Stringin əvvəllər mümkün olan ən kiçik uzunluğunu təyin edin.

Giriş. Uzunluğu 105-dan çox olmayan, yalnız 0 və 1 simvollarından ibarət bir string verilir.

Çıxış. Hüseyinin əvvəlki stringinin mümkün olan ən kiçik uzunluğunu çap edin.

Nümunə giriş 1
01010010
Nümunə çıxış 1
8
Nümunə giriş 2
1001110
Nümunə çıxış 2
1
Problemi açıq
Həll

Gəlin s giriş stringini nəzərdən keçirək — Huseyn bütün əməliyyatları etdikdən sonra əldə edilən string. İki göstəricini: i=0 stringin başında və j=n−1 sonunda təyin edək.

Əgər si​=sj​ olarsa, deməli, stringin sonundakı simvollar müxtəlifdir: ya solda 0 və sağda 1, ya da solda 1 və sağda 0. Bu, əvvəlki stringin s[i+1...j−1]-dan genişləndirilə biləcəyini bildirir. Bu halda, hər iki göstəricini bir mövqe içəriyə doğru hərəkət etdirib s[i...j]-nin Huseynin əməliyyatları ilə əldə olunub-olunmadığını yenidən yoxlayın.

Halbuki, cari s[i...j] substringi si​=sj​ olana qədər bu əməliyyatdan davam edə bilməz. Uzunluğunu çap edin — bu, Huseynin saxladığı orijinal stringdir.

Nümunə

Hüseynin əməliyyatlarını əks etdirək.

String s="1" idi, bu da Huseynin əvvəlki stringidir.

Alqoritmin həyata keçirilməsi

Giriş stringini oxuyun və onun uzunluğunu hesablayın, res dəyişənində saxlayın.

cin >> s;
res = s.size();

İki göstəricini i=0 stringin başlanğıcında və j=n−1 stringin sonunda təyin edin.

i = 0; j = s.size() - 1;

Əgər si​=sj​ olarsa, deməli, stringin sonundakı simvollar müxtəlifdir. Huseyn, substring s[i...j]-ni substring s[i+1...j−1]-dən almış ola bilər.

while ((i < j) && (s[i] != s[j]))
{

Hər iki göstəricini bir mövqe içəriyə doğru hərəkət etdirin və cari res uzunluğunu azaldın.

  i++; j--;
  res -= 2;
}

Cavabı çap edin.

cout << res << endl;
Eolymp #11244. İki ədədin cəmi

Verilmiş massiv A, artan sırada düzülmüş n tam ədəd var. x-ə bərabər olan (Ai​,Aj​) cütünün olub olmadığını müəyyən edin, burada i<j.

Giriş. İlk sətirdə iki tam ədəd n (n≤105) və x (x≤106) var. İkinci sətirdə n müsbət tam ədəd var, hər biri 106-dan böyük deyil.

Çıxış. Əgər belə bir cüt varsa "BƏLİ" yazın, əks halda "YOX" yazın.

Nümunə giriş 1
10 13
1 3 5 6 8 10 11 11 11 16
Nümunə çıxış 1
BƏLİ
Nümunə giriş 2
8 61
5 5 8 12 16 21 44 50
Nümunə çıxış 2
YOX
Problemi açıq
Həll

Gəlin v giriş ədədləri massivini nəzərdən keçirək. İki göstəricini i=0 massivinin başlanğıcında və j=n−1 massivinin sonunda təyin edin. Massiv artıq problem şərtlərinə əsasən sıralanmışdır.

Göstəricilər i və j görüşmədiyi müddətdə, aşağıdakı əməliyyatları yerinə yetirin:

  • Əgər vi​+vj​=x olarsa, tələb olunan cüt tapılmışdır. Çap edin və proqramı dayandırın.

  • Əgər vi​+vj​<x olarsa, göstərici i-ni bir mövqe sağa hərəkət etdirin. Bu halda vi​+vj​ artacaq;

  • Əgər vi​+vj​>x olarsa, göstərici j-ni bir mövqe sola hərəkət etdirin. Bu halda vi​+vj​ azalacaq;

Nümunə

Gəlin ilk testi nəzərdən keçirək. Göstəriciləri başla. Alqoritmin işləməsini simulyasiya edək. x=13-dir, 13-ə bərabər olan iki ədəd axtarırıq.

Alqoritmin həyata keçirilməsi

Giriş məlumatlarını oxuyun.

scanf("%d %d", &n, &x);
v.resize(n);
for (i = 0; i < n; i++)
  scanf("%d", &v[i]);

Göstəriciləri təyin edin.

int i = 0, j = v.size() - 1;

Göstərici i-ni irəlilədin və j-ni gerilədin.

while (i < j)
{

Əgər vi​+vj​=x olarsa, tələb olunan cüt tapılmışdır. Çap edin və proqramı dayandırın.

  if (v[i] + v[j] == x)
  {
    printf("BƏLİ\n");
    return 0;
  }

Əgər vi​+vj​<x olarsa, göstərici i-ni bir mövqe sağa hərəkət etdirin;

Əgər vi​+vj​>x olarsa, göstərici j-ni bir mövqe sola hərəkət etdirin;

  if (v[i] + v[j] < x) i++; else j--;
}

Əgər tələb olunan cüt tapılmayıbsa, "YOX" çap edin.

printf("YOX\n");
Eolymp #11246. Üç ədədin cəmi

Verilmiş A tam ədəd massivində x ədədinə bərabər olan (Ai​,Aj​,Ak​) ədədlərini tapın. Bütün indekslər i,j,k fərqli olmalıdır.

Giriş. İlk sətirdə massiv ölçüsü n (n≤3⋅104) və x (∣x∣≤109) dəyəri var. İkinci sətirdə n tam ədəd var, hər biri 108-dan böyük deyil.

Çıxış. Əgər tələb olunan üçlük varsa, onu istənilən sırada çap edin. Əgər bir neçə üçlük varsa, hər hansı birini çap edin. Əgər tələb olunan üçlük yoxdursa, −1 çap edin.

Nümunə giriş
8 19
20 3 5 1 15 7 17 12
Nümunə çıxış
1 3 15
Problemi açıq
Həll

Gəlin a0​,a1​,...,an−1​ giriş massivini nəzərdən keçirək. Mümkün olan bütün indeksləri k=0,1,...,n−3 olaraq dövr edin. Sonra, hər bir k dəyəri üçün i>k və ai​+aj​=x−ak​ (i<j) olan indeks cütlərini tapın. Bu, sıralanmış massivdə iki göstərici texnikası ilə xətti vaxtda əldə edilə bilər.

Alqoritmin həyata keçirilməsi

Giriş məlumatlarını oxuyun.

cin >> n >> x;
v.resize(n);
for (i = 0; i < n; i++)
  cin >> v[i];

Giriş massivini sıralayın.

sort(v.begin(), v.end());

k=0,1,...,n−3 dəyərləri üçün dövr edin.

for (k = 0; k < n - 2; k++)
{

i>k və vi​+vj​=x−vk​ (i<j) indeks cütlərini tapın. i və j indekslərini təyin edin.

  i = k + 1; j = n - 1;
  s = x - v[k];

İki göstərici texnikasından istifadə edərək istənilən cüt (i,j)-ni tapın.

  while (i < j)
  {
    if (v[i] + v[j] == s)
    {

Əgər (i,j) cütü tapılmışdırsa, istənilən ədədləri (vk​,vi​,vj​) çap edin.

      printf("%d %d %d\n", v[k], v[i], v[j]);
      return 0;
    }

Əgər v[i]+v[j]<s olarsa, göstərici i-ni bir mövqe sağa hərəkət etdirin;

Əgər v[i]+v[j]>s olarsa, göstərici j-ni bir mövqe sola hərəkət etdirin;

    if (v[i] + v[j] < s) i++; else j--;
  }
}

Əgər ədədlərin üçlüyü tapılmadısa, −1 çap edin.

cout << -1 << endl;
Eolymp #11286. İki qat daha böyük

Verilmiş sıralanmış A massivində n tam ədəd var. Hər bir indeks i üçün, Ai​ və 2⋅Ai​ arasında olan elementlərin sayını tapın, daxil olmaqla.

Giriş. İlk sətirdə A massivinin ölçüsü n (n≤105) var. İkinci sətirdə n tam ədəd, hər biri 0-dan 109-a qədər, sıralanmış olaraq var.

Çıxış. n tam ədəd çap edin. Hər bir i (1≤i≤n) üçün, Ai​ və 2⋅Ai​ arasında, daxil olmaqla, olan elementlərin sayını çap edin.

Nümunə giriş
10
1 2 3 4 5 6 7 8 9 10
Nümunə çıxış
2 3 4 5 6 5 4 3 2 1
Problemi açıq
Həll

A[i...j] intervalı yaxşı sayılır əgər içindəki ədədlər [Ai​;2⋅Ai​] intervalında yerləşirsə (yəni Aj​≤2⋅Ai​).

İki göstərici i və j istifadə edərək bir sürüşdürmə pəncərəsi yaradaq və onu saxlayaraq belə bir şəkildə saxlayaq ki, cari interval [i...j] yaxşı olsun, eyni zamanda [i...j+1] isə pis olsun.

Məsələn, aşağıdakı ardıcıllıq üçün:

  • [2;2],[2;3],[2;4] və [2;5] intervalı yaxşıdır.

  • [2;6],[2;7] intervalı pisdir.

Əgər Aj​≤2⋅Ai​ olarsa, cari intervalı A[i...j+1] ilə genişləndirin. Əks halda, onu A[i+1...j] ilə daraldın. i-ni hərəkət etdirmədən əvvəl Ai​ və 2⋅Ai​ arasında, daxil olmaqla, olan elementlərin sayını çap edin. Bu, j−i-yə bərabərdir.

Alqoritmin mürəkkəbliyi xətti, yəni O(n)-dir.

Nümunə

Verilmiş nümunə üçün göstəricilərin hərəkətini düşünək.

Verilmiş şərtlər üçün Aj​≤2⋅Ai​ olduğuna görə, göstərici j-ni irəliləyin.

İndi Aj​>2⋅Ai​. Göstərici i-ni irəliləmək lazımdır. Lakin, onu hərəkət etdirməzdən əvvəl Ai​ və 2⋅Ai​ arasında, daxil olmaqla, olan elementlərin sayını çap edin. Bu, j−i=6−2=4-ə bərabərdir.

Aj​≤2⋅Ai​ olduğu müddətdə j-ni irəliləyin.

İndi Aj​>2⋅Ai​. i=3 üçün cavabı çap edin (bu, j−i=8−3=5-dir) və i-ni 1 artırın.

Alqoritmin həyata keçirilməsi

Giriş məlumatlarını oxuyun.

scanf("%d", &n);
for (i = 0; i < n; i++)
  scanf("%d", &a[i]);

Göstəriciləri i=j=0 ilə təyin edin.

i = j = 0;

Hər bir i<n dəyəri üçün cavab tapana qədər göstəriciləri irəliləyin.

while (i < n) // [i..j]
{

Əgər Aj​≤2⋅Ai​ (və j massiv sərhədlərini keçməyibsə, yəni j<n), cari intervalları A[i...j+1] ilə genişləndirin.

  if ((j < n) && (a[j] <= 2 * a[i])) j++;
  else
  {

Əgər Aj​>2⋅Ai​ olarsa, i indeksi üçün cavabı çap edin və i-ni bir artırın.

    printf("%d ", j - i);
    i++;
  }
}
Eolymp #10682. Xorvatiya sahili boyunca otellər

Gözəl Adriatik sahili boyunca n otel var. Hər bir otelin qiyməti avro ilə ifadə edilir. Petr lotereyada m avro qazandı. İndi o, bu ardıcıl otellərin cəminin mümkün olduğu qədər böyük olmasını istəyir, amma m-i keçməməlidir.

Maksimal mümkün qiyməti hesablamağınız lazımdır.

Giriş. İlk sətirdə iki tam ədəd n və m (1≤n≤3⋅105,1≤m<231) var. Növbəti sətirdə n müsbət tam ədəd var, sahil boyunca yerləşən otellərin qiymətləri.

Çıxış. İstənilən qiymətləri çap edin (bütün testlərdə 0-dan böyük olacaq).

Nümunə giriş
5 12
2 1 3 4 5
Nümunə çıxış
12
Problemi açıq
Həll

Otel qiymətlərini a massivində saxlayın. [i...j] intervalını yaxşı sayacağıq, əgər içindəki otel qiymətləri m-i keçməsə.

Gəlin iki indeks i və j ilə sürüşdürmə pəncərəsi tətbiq edək, belə ki, cari interval [i...j] yaxşı olsun. s isə cari intervallardakı otel qiymətlərinin cəmini saxlayır. Cari intervalda olan bütün ədədlər q queue-da saxlanılır.

Nümunə

Gəlin göstəricilərin hərəkətini bu nümunə üçün düşünək.

Maksimum qiyməti, bütün yaxşı intervallardakı qiymətlərin içində tapın.

Alqoritmin həyata keçirilməsi

Giriş məlumatlarını oxuyun.

scanf("%d %lld", &n, &m);

İndiki dəyişənləri təyin edin:

  • res-də, bütün işlənmiş yaxşı intervallardakı qiymətlərin maksimumunu hesablayın;

  • s-də, cari intervallardakı ədədlərin cəmini saxlayın. Cari intervallardakı bütün ədədlər q queue-da saxlanılır;

s = res = 0;

Otel qiymətlərini ardıcıl işləyin.

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

Cari otelin qiymətini oxuyun və onu queue-ya əlavə edin.

  scanf("%d", &val);
  q.push(val);

Cari intervallardakı s cəmini yeniləyin. Bütün cari intervallardakı elementlər q queue-da saxlanılır.

  s += val;

Əgər cari intervallardakı cəmi s, m-i keçərsə, intervallardan başından elementləri çıxarın.

  while (s > m)
  {
    s -= q.front();
    q.pop();
  }

Yaxşı intervallardakı ədədlərin cəmi arasında maksimum qiyməti res-i yeniləyin (otellərin qiymətləri m-i keçməməlidir).

  if (s > res) res = s;
}

Cavabı çap edin.

printf("%lld\n", res);
Eolymp #11721. Alt massivlərin cəmi 1

Verilmiş n müsbət tam ədəd massivini, x-ə bərabər olan alt massivlərin sayını tapın.

Giriş. İlk sətirdə massiv ölçüsü n (1≤n≤2⋅105) və hədəf cəmi x (1≤x≤109). Növbəti sətirdə n ədəd a1​,a2​,…,an​ (1≤ai​≤109) — massiv məzmunu.

Çıxış. Lazım olan alt massivlərin sayını çap edin.

Nümunə giriş
5 7
2 4 1 2 7
Nümunə çıxış
3
Problemi açıq
Həll

Gəlin iki göstərici i və j ilə sürüşdürmə pəncərəsi tətbiq edək. Hər bir sabit i=1,2,... üçün [i...j] intervalını mümkün qədər genişləndirin, belə ki, elementlərinin cəmi x-i keçməsin. Başqa sözlə, hər i üçün, [i...j] intervalındakı elementlərin cəminin x-i keçmədiyi, [i...j+1] intervalındakı elementlərin cəminin x-i keçdiyi ən böyük j-ni axtarın.

Gəlin s-ni [i...j] intervalındakı ədədlərin cəmi ilə saxlayırıq. Əgər s+a[j+1]≤m olarsa, [i...j+1] intervalını genişləndirin. Əks halda, [i+1...j] intervalını daraldın. x-ə bərabər olan alt massivlərin sayını hesablayın.

Nümunə

Gəlin verilmiş nümunə üçün göstəricilərin hərəkətini araşdıraq.

  1. i=0, j irəliləyir ki, [i...j] intervalındakı ədədlərin cəmi x=7-i keçməsin. [0...2] intervalında dayanırıq, çünki burada ədədlərin cəmi 7-dir, [0...3] intervalında isə cəmi artıq 9-dur.

  2. i=1, j irəliləyir ki, [i...j] intervalındakı ədədlərin cəmi x=7-i keçməsin. [1...3] intervalında dayanırıq, çünki burada cəmi 7-dir, [1...4] intervalında isə cəmi 14-dür.

  3. i=2, nəzərdən keçirilən interval [2...3]-dür. Burada ədədlərin cəmi 3-dür, amma [2...4] intervalında cəmi 10-dur, bu da 7-dən çoxdur.

  4. i=3, nəzərdən keçirilən interval [3...3]-dür. Burada ədədlərin cəmi 2-dir, amma [3...4] intervalında cəmi 9-dur, bu da 7-dən çoxdur.

  5. i=4, nəzərdən keçirilən interval [4...4]-dür. Burada ədədlərin cəmi 7-dir.

x=7 olan alt massivlərin sayı 3-dür. Onlar 0,1 və 4 indekslərində başlayırlar.

Alqoritmin həyata keçirilməsi

Bir massiv elan edin.

#define MAX 200001
long long a[MAX];

Giriş məlumatlarını oxuyun.

scanf("%d %lld", &n, &x);
for (i = 0; i < n; i++)
  scanf("%lld", &a[i]);

Başlanğıc intervalını [i...j]=[0;0] olaraq təyin edin. Bu intervaldakı ədədlərin cəmi s=0-dir.

s = j = 0;

Hər bir i dəyəri üçün ardıcıl [i...j] intervallarını işləyin.

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

Sabit sol son i olan [i...j] intervalında j-nin ən böyük dəyərini tapın ki, cəmi x-i keçməsin.

  while ((j < n) && (s + a[j] <= x)) s += a[j++];

Cari [i...j] intervalındakı ədədlərin cəmi s x-ə bərabər olduqda, istədiyimiz alt massiv sayını cnt-ni artırın.

  if (s == x) cnt++;

[i+1...j] intervalındakı s-ni yenidən hesablayın.

  s -= a[i];
}

Cavabı çap edin.

printf("%lld\n", cnt);
Eolymp #9631. Ardıcıllıqların müsabiqəsi

Ziya sabah ardıcıllıq müsabiqəsində iştirak edəcək. x≥0 ədədi, bir ardıcıllığın zirvəsi sayılır, əgər ardıcıllıq 1,2,3,...,x−1,x,x−1,...,3,2,1 bu ardıcıllığın alt ardıcıllığıdır. Hər bir ardıcıllığın gücü onun ən böyük zirvəsi sayılır.

Sabah bütün tələbələr müsabiqəyə gedəcəklər və ən güclü ardıcıllığın qalibi olacaq. Ziya a1​,a2​,a3​,...,an​ ardıcıllığına sahibdir. O, bu gün bütün ardıcıllıqlara üstünlük verərək daha güclü ardıcıllığı seçmək istəyir. Ancaq Ziya öz ardıcıllığının gücünü bilmir, lakin qalib olmaq istəyir. Ona kömək edin ki, öz ardıcıllığının gücünü hesablasın.

Giriş. İlk sətirdə Ziyanın ardıcıllığında olan ədədlərin sayı n (1≤n≤105) var. Növbəti sətirdə n tam ədəd ai​ (1≤ai​≤105) — ardıcıllığın elementləridir.

Çıxış. Bir ədəd çap edin — verilmiş ardıcıllığın gücüdür.

Nümunə giriş 1
2
2 10
Nümunə çıxış 1
0
Nümunə giriş 2
3
1 2 3
Nümunə çıxış 2
1
Nümunə giriş 3
5
1 10 2 3 1
Nümunə çıxış 3
2
Problemi açıq
Həll

Gəlin v giriş ədədləri massivini nəzərdən keçirək. İki göstəricini i=0 massivinin əvvəlində və j=n−1 massivinin sonunda təyin edək. Gücünü dəyişəndə k-ni sayırıq. Başlanğıcda, k=1-dir.

Göstəricilər i və j görüşənə qədər aşağıdakı əməliyyatları yerinə yetirin:

  1. k-ya bərabər olmayan ədədlərə rast gəlmədiyi müddətdə, göstərici i-ni sağa doğru bir yerə keçirin.

  2. k-ya bərabər olmayan ədədlərə rast gəlmədiyi müddətdə, göstərici j-ni sola doğru bir yerə keçirin.

  3. Hər iki göstərici k-ya bərabər olduqda, k-ni bir artırın və hər bir göstəricini müvafiq istiqamətdə bir mövqe irəlilədin.

Alqoritm tamamlandıqda, cavab k−1 dəyəri olacaq.

Nümunə

İkinci testi nəzərdən keçirək. Göstəriciləri başla. Göstərici i-ni sağa, göstərici j-ni sola doğru hərəkət etdirin ki, hər iki göstərici 1-ə bərabər olsun.

Göstərici i-ni sağa, göstərici j-ni sola doğru hərəkət etdirin ki, hər iki göstərici 2-yə bərabər olsun.

Göstəricilər görüşür, alqoritmi dayandırın. Cavab k=2 olacaq.

Alqoritmin həyata keçirilməsi

Giriş məlumatlarını oxuyun.

scanf("%d", &n);
v.resize(n);
for (i = 0; i < n; i++)
  scanf("%d", &v[i]);

Göstəriciləri v massivinin başlanğıcında və sonunda yerləşdirin.

int i = 0, j = v.size() - 1;

Güc dəyişənini sayın.

k = 1;
while (i <= j)
{

Göstərici i-ni sağa doğru keçirin ki, k-ya bərabər olmayan ədədlərə rast gəlməyəsiniz.

  if (v[i] != k) i++;

Göstərici j-ni sola doğru keçirin ki, k-ya bərabər olmayan ədədlərə rast gəlməyəsiniz.

  if (v[j] != k) j--;

Hər iki göstərici k-ya bərabər olduqda, k-ni artırın.

  if (v[i] == k && v[j] == k) k++;
}

Cavabı çap edin.

printf("%d\n", k - 1);

Problemlərin siyahısı

  • 2098. İnvertor

  • 11387. Kart oyunları

  • 11388. Kart oyunları 2

  • 11389. Hüseynin oyunu

  • 11244. İki ədədin cəmi

  • 11246. Üç ədədin cəmi

  • 11286. İki qat daha böyük

  • 10682. Xorvatiya sahili boyunca otellər

  • 11721. Alt massivlərin cəmi 1

  • 9631. Ardıcıllıqların müsabiqəsi

  • 9632. Ən yaxşı komanda

  • 10568. Bronzdan olan almaz toplayıcı

  • 11247. Ən çox su saxlayan konteyner

  • 11340. Radio 106 FM


18

Şərhlər (5)

Yüklənir

Bir an, serverdən məlumat alınır
azimzadenihad•11 ay öncə

thanks for all

0
Eltaj13•11 ay öncə

Thanks for the problems!

1
drizzy•12 ay öncə

Thanks for the problems! Will there be future topic contests like these ?

2
medv•12 ay öncə•2-ci təftiş

drizzy Thanks a lot if you liked it. By the way, problems "Competition of sequences", "The best team" and "Radio 106 FM" are taken from the past official Azerbaijan School Competitions

7
drizzy•12 ay öncə

medv Please continue this series of topic wise contests. Thanks

4