Advertisement
Hezov

Raza ONI VII 2022

Mar 29th, 2024 (edited)
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.26 KB | Source Code | 0 0
  1. /**Aici ai sursa mea de la problema Raza ONI VII 2022 cu explicatii. .
  2. O poti citi si cand ne vedem iti explic daca e ceva ce nu ai inteles.  ~ George   */
  3. #include <fstream>
  4. using namespace std;
  5. ifstream cin("raza.in");
  6. ofstream cout("raza.out");
  7. /**
  8.    Patratul de latura razei ce incepe din coord (xA,yA).
  9.    A             B
  10.     -------------
  11.     |           |
  12.     |           |
  13.     |           |
  14.     |           |
  15.     -------------
  16.    D             C
  17.  
  18. */
  19. int Sec[100001];
  20. int main()
  21. {
  22.     int cerinta , n ,s ;
  23.     cin>>cerinta>>n>>s;
  24.     if(cerinta==1)
  25.     {
  26.         int cnt = 0;
  27.         for(int i  = 1;i<=n;i++)
  28.         {
  29.             //cout<<"Roverul "<<i<<":\n";
  30.             int l , c , r;
  31.             bool intersect = false;
  32.             cin>>l>>c>>r;
  33.  
  34.             /**Verificam daca AB se intersecteaza cu diagonala.
  35.             Diagonala in cazul nostru se afla pe pozitia unde l=c iar c creste cu raza - 1.
  36.             Se intersecteaza daca in poz intitiala e inaintea diagonalei sau pe ea (c<=l).
  37.             Iar pozitia finala a coloanei este mai mare sau egala cu coord liniei.  */
  38.  
  39.             if(c<=l&&c+r - 1>=l)
  40.             {
  41.                  intersect = true;
  42.                 // cout<<"AB\n";
  43.             }
  44.  
  45.             /**Verificam daca AD se intersecteaza cu diagonala. Linia creste cu raza.
  46.             Se poate intersecta daca in poz intitiala este deasupra diagonalei si coborand
  47.             se intersecteaza cu aceasta. */
  48.             if(l<=c&&l+r - 1>=c)
  49.             {
  50.                 intersect = true;
  51.                // cout<<"AD\n";
  52.             }
  53.  
  54.             /**
  55.                 Mai avem de verificat BC si DC.
  56.                 DC fiind paralel cu AB verificarea se face similar
  57.                 doar ca coordonata liniei incepe de la l+r in loc de l
  58.                 iar la BC se face ca la AD dar coordonata coloanei incepe cu c+r.
  59.             */
  60.             int cl = l + r - 1; ///Coordonata liniei.
  61.             int cc = c + r - 1; ///Coordonata coloanei.
  62.  
  63.             ///DC
  64.             if(c<=cl&&c+r - 1>=cl)
  65.             {
  66.                  intersect = true;
  67.                 // cout<<"DC\n";
  68.             }
  69.             ///BC
  70.             if(l<=cc&&l+r - 1>=cc)
  71.             {
  72.                 intersect = true;
  73.                 //cout<<"BC\n";
  74.             }
  75.             ///Daca s-a intersectat macar odata incrementam contorul.
  76.             if(intersect == true)
  77.                 cnt++;
  78.         }
  79.         cout<<cnt;
  80.     }
  81.  
  82.     if(cerinta==2)
  83.     {
  84.         /**Acum pe langa intersectia cu diagonala , ne intereseaza mai exact
  85.         in a cata secunda are loc aceasta intersectie. Avem urmatoarea problema:
  86.         numaram de mai multe ori aceiasi intersectie cand intersectia are loc pe un
  87.         punct al patratului.
  88.         EX: 3 3 . L = 3 , C = 3 , R = 3. Intersectiile au loc in punctele
  89.         A si C . Pentru ca punctul A face parte si din AB si din AD il vom numara de doua ori.
  90.         La fel se intampla si pentru C,  fiind in BC si DC.
  91.  
  92.         Solutia e simpla : Mai intai verificam pentru AB inclusiv punctul B daca are loc intersectie acolo.
  93.         Apoi pentru BC verficam secundele de la  R+1 pana la 2*R-1 .  Adica verificam daca linia in intervalul
  94.         l+1 -> l+r-1 se intersecteaza cu diagonala. Similar facem si pentru restul.
  95.         Partea asta poti sa imi ceri sa ti-o explic si vei intelege foarte usor cu un desen.*/
  96.  
  97.         /**
  98.             Putem avea maxim 2 intersectii. Sa spunem ca stim secundele la care
  99.             au loc respectivele intersectii(-1 daca nu au loc). Ce facem apoi?
  100.             Putem marca pe o scara a timpului secundele in care se intersecteaza.
  101.  
  102.             Sa consideram un tablou Sec in care marcam cate rovere se intersecteaza in
  103.             acea secunda. Daca Sec[5] = 3 inseamna ca in secunda 5, 3 rovere se intersecteaza
  104.             cu diagonala principala.
  105.  
  106.             Sa luam raza = 6 si o intersectie in secunda 9.(x = 9).
  107.             Perioada este 4 * raza - 4 = 20.
  108.             Prima intersectie va avea loc in secunda 20*0 + 9.
  109.             A doua intersectie va avea loc in secunda 20*1 + 9.
  110.             A treia intersectie va avea loc in secunda 20*2 + 9.
  111.             Si asa mai departe. Putem marca aceste secunde in stil ciur :
  112.  
  113.             for(int i = x ; i<=S; i+=perioada)
  114.                 Sec[i]++;
  115.  
  116.             ANALIZA TIMPULUI IN CEL MAI RAU CAZ :
  117.             Cea mai mica perioada este 8 (pentru r = 3) asadar o astfel de marcare
  118.             in cel mai rau caz posibil , unde S = 100k va efectua 100k/8 operatii
  119.             pentru un singur rover cu o singura intersectie (12.5k). Pentru doua intersectii
  120.             vor fi 25k operatii. In restrictii ni se spune ca sunt maxim 1000 rovere care se intersecteaza
  121.             cu diagonala. Asadar in cel mai rau caz putem avea 25k * 1000 (25 mil operatii in care adunam in Sec[i]).
  122.             Am putea sa verificam de fiecare data cand adaugam frecventa daca este cea pe care o cautam dar atunci am
  123.             face 25 mil comparatii asa ca e mai bine sa parcurgem inca odata Sec la final decat sa verificam de fiecare
  124.             data daca secunda este raspunsul pe care il cautam.
  125.  
  126.  
  127.             Solutia oficiala propune sa folosim 3 vectori , in care sa pastram pozitia intersectiei 1 , poz intersectiei 2
  128.             si perioada fiecarui rover. Nu este necesar. Daca au loc intersectii marcam , daca nu , nu.
  129.             */
  130.         for(int i = 1;i<=n;i++)
  131.         {
  132.             //cout<<"Rover "<<i<<": \n";
  133.             int l , c , r;
  134.             cin>>l>>c>>r;
  135.             ///Secundele de la fiecare punct.
  136.             int secA = 1 , secB = r , secC = 2*r-1 , secD = 3*r-2;
  137.             int perioada = 4 * r - 4, cl = l+r-1, cc = c+r-1;
  138.             int punct1 = -1 , punct2 = -1;
  139.             ///Avem intersectie in AB
  140.             if(c<=l&&c+r - 1>=l)
  141.                 punct1 = secA + (l - c);
  142.             ///Avem intersectie pe BC
  143.             if(l+1<=cc&&l+r-1>=cc)
  144.             {
  145.                 if(punct1==-1)
  146.                     punct1 = secB + (cc - l);
  147.                 else punct2 = secB + (cc - l);
  148.             }
  149.             ///Avem intersectie pe CD
  150.             if(cc>=cl&&cc-r+1<=cl)
  151.             {
  152.                 if(punct1 == -1)
  153.                     punct1 = secC + (cc - cl);
  154.                 else punct2 = secC + (cc-cl);
  155.             }
  156.             ///Avem intersectie pe DA
  157.             if(cl-1>=c&&cl-r+2<=c)
  158.             {
  159.                 if(punct1 == -1)
  160.                     punct1 = secD + (cl - c);
  161.                 else punct2 = secD + (cl - c);
  162.             }
  163.             /**if(punct1!=-1)
  164.                 cout<<"Punct 1: "<<punct1<<'\n';
  165.             if(punct2!=-1)
  166.                 cout<<"Punct 2: "<<punct2<<'\n'; */
  167.  
  168.             ///Acum ca avem secundele punctelor marcam pe Sec.
  169.             if(punct1!=-1)
  170.             {
  171.                 for(int i = punct1;i<=s;i+=perioada)
  172.                     Sec[i]++;
  173.             }
  174.             if(punct2!=-1)
  175.             {
  176.                 for(int i = punct2;i<=s;i+=perioada)
  177.                     Sec[i]++;
  178.             }
  179.         }
  180.         int maxi = -1 , secmin = -1;
  181.         for(int i = 1;i<=s;i++)
  182.         {
  183.             if(Sec[i]>maxi)
  184.                 maxi = Sec[i], secmin = i;
  185.         }
  186.         cout<<maxi<<' '<<secmin;
  187.     }
  188.     return 0;
  189. }
  190.  
Tags: C++
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement