Cod sursa(job #953056)

Utilizator primulDarie Sergiu primul Data 24 mai 2013 18:31:54
Problema Hotel Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.24 kb
//Problema se rezolva in O(p*logn) cu Lazy Update pe Arbori de Intervale
#include <fstream>
  
using namespace std;
  
//Un nod al arborelui de intervale
struct nod
{
   int st,dr;
   int pref,suf,best;
   //bool lenes;
   //int val_lenes;
  
   nod()
   {
      st=0;
      dr=0;
      pref=0;
      suf=0;
      best=0;
     // lenes=0;
     // val_lenes=0;
   }
}arb[262144]; //Arborele de intervale este retinut in memorie sub forma de heap
  
//Aceasta functie construieste arborele
void build(int st,int dr,int poz)
{
   arb[poz].st=st;
   arb[poz].dr=dr;
   arb[poz].suf=arb[poz].pref=arb[poz].best=(dr-st+1);
   //arb[poz].lenes=0;
   //arb[poz].val_lenes=0;
  
   if(st<dr)
   {
      int mijl=(st+dr)>>1;
      build(st,mijl,poz<<1);
      build(mijl+1,dr,(poz<<1)+1);
   }
}
  
//Functie de maxim
inline int maxim(int a,int b)
{
   if(a>b)
     return a;
   return b;
}
  
//Functie de maxim (cu trei numere)
inline int maxim(int a,int b,int c)
{
   return maxim(maxim(a,b),c);
}
  
//Recalculeaza informatiile dintr-un nod in functie de cele din fii sai deja calculati
inline void recompute(nod &a,nod b,nod c)
{
   if((b.dr-b.st+1)==b.pref)    
      a.pref=b.pref+c.pref;
   else
      a.pref=b.pref;
       
   if((c.dr-c.st+1)==c.suf)
     a.suf=c.suf+b.suf;
   else
     a.suf=c.suf;  //GRESEALA: scrisesem a.pref in loc de a.suf!!!!!!
    
   a.best=maxim(b.best,c.best,b.suf+c.pref);
}
  
//Face lenesi cu valoarea val fii nodului arb[poz]
inline void fii_lenesi(int poz,int val)
{
    arb[poz<<1].suf=arb[poz<<1].pref=arb[poz<<1].best=val*(arb[poz<<1].dr-arb[poz<<1].st+1);
    arb[(poz<<1)+1].suf=arb[(poz<<1)+1].pref=arb[(poz<<1)+1].best=val*(arb[(poz<<1)+1].dr-arb[(poz<<1)+1].st+1);
}
  
//Pune valoarea 1 pe un interval
void update_0(int st,int dr,int poz)
{
   //Daca intervalul curent este total exclus din arb[poz]
   if((arb[poz].dr<st) || (arb[poz].st>dr))
     return;
      
   //Daca arb[poz] este un singur element ce apartine intervalui
   if(arb[poz].st==arb[poz].dr && arb[poz].st==st)
   {
       arb[poz].pref=arb[poz].suf=arb[poz].best=1;
       return;
   }
    
   //Daca intervalul e gol
   if(arb[poz].best==0)
       fii_lenesi(poz,0);
   else if(arb[poz].best==(arb[poz].dr-arb[poz].st+1)) //Daca intervalul e plin
       fii_lenesi(poz,1);
   if(arb[poz].st==st && arb[poz].dr==dr) //Daca am "nimerit" intervalul
   {
       arb[poz].pref=arb[poz].suf=arb[poz].best=(arb[poz].dr-arb[poz].st+1);
       return;
   }
    
   //Impartim in 2 intervalul
   int mijl=(arb[poz].st+arb[poz].dr)>>1;
   if(dr<=mijl)
     update_0(st,dr,poz<<1);
   else if(st>mijl)
     update_0(st,dr,(poz<<1)+1);
   else
     update_0(st,mijl,poz<<1),update_0(mijl+1,dr,(poz<<1)+1);
   recompute(arb[poz],arb[poz<<1],arb[(poz<<1)+1]);
}
 
//Idem cu update_0
void update_1(int st,int dr,int poz)
{
   if((arb[poz].dr<st) || (arb[poz].st>dr))           
     return;
   if(arb[poz].st==arb[poz].dr && arb[poz].st==st)
   {
       arb[poz].pref=arb[poz].suf=arb[poz].best=0;
       return;
   }
   if(arb[poz].best==0)
       fii_lenesi(poz,0);
   else if(arb[poz].best==(arb[poz].dr-arb[poz].st+1))
       fii_lenesi(poz,1);
   if(arb[poz].st==st && arb[poz].dr==dr)
   {
       arb[poz].pref=arb[poz].suf=arb[poz].best=0;
       return;
   }
    
   int mijl=(arb[poz].st+arb[poz].dr)>>1;
   if(dr<=mijl)
     update_1(st,dr,poz<<1);
   else if(st>mijl)
     update_1(st,dr,(poz<<1)+1);
   else
     update_1(st,mijl,poz<<1),update_1(mijl+1,dr,(poz<<1)+1);
   recompute(arb[poz],arb[poz<<1],arb[(poz<<1)+1]);
}
  
int main()
{
    ifstream cin("hotel.in");
    ofstream cout("hotel.out");
     
    int n,p,cod,i,a,b;
     
    //Citim marimea intervalului arb[1] respectiv numarul de intrebari
    cin>>n>>p;
    build(1,n,1);
     
    //Citim si solutionam intrebarile
    for(i=0;i<p;i++)
    {
       cin>>cod;
       if(cod<3)
       {
          cin>>a>>b;
          b=(a+b-1);
       }
        
       if(cod==1)
         update_1(a,b,1);
       else if(cod==2)
         update_0(a,b,1);
       else
          cout<<arb[1].best<<'\n';                 
    }
     
    cin.close();
    cout.close();
    //system("PAUSE");
    return 0;
}