Hezov

Indicatii KthSumSecv

Jul 26th, 2024
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.83 KB | Source Code | 0 0
  1. /**
  2.     Problema propusa va folosi urmatoarele :
  3.     - Cautare binara pe rezultat
  4.     - Fereastra glisanta / sliding window technique
  5.  
  6.     Enunt pe scurt : Se sorteaza crescator toate sumele
  7.     subsecventelor dintr-un sir de valori si le punem
  8.     intr-un tablou v. Se cere afisarea elementului v[k].
  9.     Ex : sir : 1,2,4 , k = 5
  10.     Subsecventele si sumele lor sunt :
  11.     (1)-> 1
  12.     (1,2)-> 3
  13.     (1,2,4)-> 7
  14.     (2)-> 2
  15.     (2,4)-> 6
  16.     (4) -> 4
  17.     Sumele sortate sunt :
  18.     1 , 2 , 3, 4 , 6 , 7.
  19.     V[k] = 6. (k=5)(Raspunsul).
  20.  
  21.     Sa spunem ca avem n elemente.
  22.     Vom avea n*(n+1)/2 subsecvente
  23.     (in exemplu n = 3 -> 3*4/2 = 6 subsevente)
  24.     Din restrictii n <= 10.000 asadar putem avea
  25.     pana la 50 de milioane de subsecvente...
  26.  
  27.     Evident nu putem simula ce ne cere problema
  28.     (eu nu propun probleme foarte usoare in caz de a-ti observat)
  29.    
  30.     REZOLVARE
  31.     F(x) - returneaza cate subsecvente sunt mai mici sau egale cu x;
  32.     Daca stim aceasta informatie stim a cata subsecventa este ultima subsecventa cu suma x.
  33.     Deci daca gasim cel mai mic x pentru care F(x) >= k atunci si elementul k din sirul sortat
  34.     va avea aceiasi suma;
  35.    
  36.    Sa luam un sir sortat de sume ale subsecventelor sa intelegem mai bine :
  37.    
  38.    Sir 1 2 4 6 6 6 8 10  (suma = 43)
  39.    Poz 1 2 3 4 5 6 7 8   (Vrem sa returnam Sir[5] = 6 (acel 6 de la mijloc.)
  40.    
  41.    Cand f(x) >= k vom salva acea pozitie evident.
  42.    k = 5 , cand F(x) < k -> st = mid+1, cand F(x) >= k -> dr = mid-1 si salvam mid ca noua solutie.
  43.                          
  44.    st = 1 , dr = 43 -> mid = 21 -> F(x) = 8 (evident toate sumele sunt mai mici decat 21) (noua solutie = mid)
  45.    st = 1, dr = 20 -> mid = 10 -> F(x) = 8 (iarasi) (noua solutie = mid)
  46.    st = 1, dr = 9 -> mid = 5 -> F(x) = 3 (de la pozitia 4 incolo sunt mai mari sumele decat 5)
  47.    st = 6, dr = 9 -> mid = 7 -> F(x) = 6 (noua solutie = mid)
  48.    st = 6, dr = 6 -> mid = 6 -> F(x) = 6 (noua solutie = mid)
  49.    st = 6, dr = 5 -> exit.  sol = 6  
  50.    
  51.    De aceea luam f(x)>=k si nu doar f(x)==k, pentru ca putem avea mai multe subsecvente cu aceiasi suma.
  52.    
  53.    Acum sper ca reiese cum ne ajuta functia F(x) si cum putem folosi rezultatele ei in cautarea binara
  54.    pentru a determina valoarea sumei de pe pozitia k. Dar pana acum am folosit doar rezultatele functiei din ochi
  55.    pentru ca putem vedea din datele exemplului..
  56.    
  57.    Acum complexitatea solutiei va fi logN ( de la cautarea binara) * ceva (complexitatea functiei F(x))
  58.    Dar stim deja ca n^2 nu este suficient de eficient deci e clar ca complexitatea necesara functiei F(x)
  59.    este O(n)... Deci cam printr-o singura trecere a elementelor va trebui sa spunem cate subsecvente
  60.    au suma mai mica sau egala decat x. Nu avem asa de multe optiuni de considerat. E clar ca vom
  61.    avea nevoie de fereastra glisanta / sliding window technique.
  62.    Vom retine suma elementelor de la i la j. Cand mutam i suma scade , cand mutam j suma creste.
  63.    Asadar daca suma de la i la j <= x atunci toate subsecventele cu j fixat acolo si cu i crescand
  64.    pana la j vor avea si ele suma mai mica sau egala decat x (suma scade) deci putem din start
  65.    sa crestem sol cu lungimea intervalului (j - i + 1).
  66.    Daca suma de la i la j este mai mare decat x atunci mutam i pana cand suma este mai mica sau egala.
  67.    
  68.    Aveti aici functia F(x) in cod.
  69.    */
  70.    int F(int x)
  71.    {  
  72.       int sol = 0; // cate subsecvente au suma mai mica sau egala decat x
  73.       int i = 1, j = 1, // cei doi pointeri
  74.       int sum = 0; // suma de la i la j
  75.       while(i<=n&&j<=n)
  76.       {
  77.           sum+=v[j];
  78.           while(sum>x) //ne asiguram ca suma e mai mica sau egala decat x.
  79.             sum-=v[i], i++; //mutam capatul din stanga al intervalului.
  80.           sol+=(j - i + 1); //crestem sol cu lungimea intervalului.
  81.           j++;
  82.       }
  83.       return sol;
  84.    }
Add Comment
Please, Sign In to add comment