Cod sursa(job #1066057)

Utilizator ctlin04UAIC.VlasCatalin ctlin04 Data 23 decembrie 2013 23:09:12
Problema Struti Scor 30
Compilator cpp Status done
Runda Teme Pregatire ACM Unibuc 2013 Marime 4.52 kb
#include<fstream>
#include<cstring>
using namespace std;
int maxheap[8100], minheap[8100];
int i,j,n,m,p,sol,nrsol,a[1005][1005],dx,dy,nrap[8100],indhmin[8100],indhmax[8100],hpmin,hpmax;

void upheap(){
    int aux=hpmin;
      while (aux>1&&minheap[aux/2]>minheap[aux]) { 
                 swap(indhmin[minheap[aux]],indhmin[minheap[aux/2]]); 
                   swap(minheap[aux],minheap[aux/2]);
                   aux/=2;
                   }
    aux=hpmax;
     while (aux>1&&maxheap[aux/2]<maxheap[aux]) { 
                 swap(indhmax[maxheap[aux]],indhmax[maxheap[aux/2]]); 
                   swap(maxheap[aux],maxheap[aux/2]);
                    aux/=2;
                   }
}

void baga(int val) {
     if (nrap[val]>0) ++nrap[val];
      else {
           ++nrap[val];
           ++hpmin; ++hpmax;
           indhmin[val]=hpmin;
           indhmax[val]=hpmax;
           maxheap[hpmax]=val;
           minheap[hpmin]=val;
           upheap();
           }
}

void scoate(int val) {
     if (nrap[val]>1) --nrap[val];
      else {
           --nrap[val];
           indhmin[minheap[hpmin]]=indhmin[val];
           minheap[indhmin[val]]=minheap[hpmin];
           --hpmin;
           int aux=indhmin[val];
           //daca trebuie fac upheap
           while (aux>1&&minheap[aux/2]>minheap[aux]) { 
                 swap(indhmin[minheap[aux]],indhmin[minheap[aux/2]]); 
                   swap(minheap[aux],minheap[aux/2]);
                   aux/=2;
                   }
           //daca trebuie fac down heap
           while (aux<=hpmin/2) {
                 int ind=aux;
                 if (minheap[2*aux]<minheap[ind]) ind=2*aux;
                 if (2*aux<hpmin&&minheap[2*aux+1]<minheap[ind]) ind=2*aux+1;
                 if (ind==aux) break;
                  else {
                       swap(indhmin[minheap[aux]],indhmin[minheap[ind]]); 
                        swap(minheap[aux],minheap[ind]);
                       aux=ind;
                   }
                  }
           //acelasi lucru pentru maxheap
           indhmax[maxheap[hpmax]]=indhmax[val];
           maxheap[indhmax[val]]=maxheap[hpmax];
           --hpmax;
            aux=indhmax[val];
           //daca trebuie fac upheap
           while (aux>1&&maxheap[aux/2]<maxheap[aux]) { 
                 swap(indhmax[maxheap[aux]],indhmax[maxheap[aux/2]]); 
                   swap(maxheap[aux],maxheap[aux/2]);
                    aux/=2;
                   }
           //daca trebuie fac down heap
           while (aux<=hpmax/2) {
                 int ind=aux;
                 if (maxheap[2*aux]>maxheap[ind]) ind=2*aux;
                 if (2*aux<hpmax&&maxheap[2*aux+1]>maxheap[ind]) ind=2*aux+1;
                 if (ind==aux) break;
                  else {
                       swap(indhmax[maxheap[aux]],indhmax[maxheap[ind]]); 
                        swap(maxheap[aux],maxheap[ind]);
                       aux=ind;
                   }
                  }
       }
}

void update() {
     int newsol=maxheap[1]-minheap[1];
     if (newsol<sol) { sol=newsol; nrsol=1; }
      else if (newsol==sol) ++nrsol;
}

void query(int x, int y) {
     int i,j,k,t;
      memset(nrap,0,sizeof(nrap)); hpmax=hpmin=0;
     for (i=1; i<=x; ++i)
      for (j=1; j<=y; ++j) baga(a[i][j]);
     update();
     k=0;
     for (i=x; i<=n; ++i)
      if (k%2==0) {
                  for (j=y+1; j<=m; ++j) {
                      for (t=i-x+1; t<=i; ++t) { baga(a[t][j]); scoate(a[t][j-y]); }
                      update();
                      }
                  if (i<n) {
                           for (j=m-y+1; j<=m; ++j){ baga(a[i+1][j]); scoate(a[i-x+1][j]); }
                            ++k; update();
                            }
                  }
       else {
            for (j=m-1; j>=y; --j) {
                for (t=i-x+1; t<=i; ++t) { baga(a[t][j-y+1]); scoate(a[t][j+1]); }
                update();
                }
            if (i<n) {
                     for (j=1; j<=y; ++j) { baga(a[i+1][j]); scoate(a[i-x+1][j]); }
                      ++k; update();
                      }
            }
}    

int main(void){
    ifstream fin("struti.in");
    ofstream fout("struti.out");
    fin>>n>>m>>p;
    for (i=1; i<=n; ++i)
     for (j=1; j<=m; ++j) fin>>a[i][j];
    for (; p>0; --p) {
          fin>>dx>>dy;
          sol=100000000; nrsol=0;
          query(dx,dy); 
          if (dx!=dy) query(dy,dx);
          fout<<sol<<" "<<nrsol<<"\n";
          }
  return(0);
}