Cod sursa(job #317677)

Utilizator mihai_floreaFlorea Mihai Alexandru mihai_florea Data 24 mai 2009 20:30:23
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.63 kb
#include <cstdio>
#include <algorithm>
using namespace std;
const int NMAX=303;
const int QMAX=20002;
const int HMAX=1000001;
int N,Q;
struct Query{
       int x1,y1,x2,y2;
       } I[QMAX];
int Sol[QMAX],t[NMAX*NMAX],b[NMAX][NMAX];
pair<int,int> tmp[QMAX],a[NMAX*NMAX];
bool U[NMAX*NMAX];
int find(int x){
    if (x!=t[x]) t[x]=find(t[x]);//path compresion with style :D
    else return x;
    }
void unite(int x,int y){
     x=find(x);y=find(y);
     if (!U[y]) return;//Unim decat doua componennte ce au fost deja analizate
     if ((rand()&1)) t[x]=y;
                else t[y]=x;
     }
int main(){
    int i,j,k;
    freopen("matrice2.in","r",stdin);
    freopen("matrice2.out","w",stdout);
    scanf("%d %d",&N,&Q);
    for (i=0;i<N;++i)
      for (j=0;j<N;++j){
          scanf("%d",&k);
          b[i][j]=k;
          a[i*N+j].first=k;
          a[i*N+j].second=i*N+j;
          }
    sort(a,a+N*N);
    
    int x1,y1,x2,y2;
    for (i=1;i<=Q;++i){
      scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
      --x1,--x2,--y1,--y2;
      I[i].x1=x1,I[i].y1=y1,I[i].x2=x2,I[i].y2=y2;
      }
    
    
    //O "cautare binara" (cu sau fara "") in paralel pt fiecare Query
    for (k=1;k<=HMAX;k<<=1);
    for (k>>=1;k>=1;k>>=1)
      {
       for (i=1;i<=Q;++i)
         tmp[i].first=Sol[i]+k,
         tmp[i].second=i;
       sort(tmp+1,tmp+Q+1);
       
       for (i=0;i<N*N;++i)
         t[i]=i,U[i]=false;
       
       for (j=Q,i=N*N-1;i>=0;--i)
        {
         U[a[i].second]=true;
         if (a[i].first<tmp[j].first)
            while (j>0 && tmp[j].first>a[i].first)
              {
               int idx=tmp[j].second;
               if (find(I[idx].x1*N+I[idx].y1)==
                   find(I[idx].x2*N+I[idx].y2))
                 Sol[idx]+=k;
               --j;
               }
         int _x,_y;
         _x=a[i].second/N;
         _y=a[i].second%N;
         if (_x>0 && b[_x-1][_y]>=a[i].first)
                unite(a[i].second,(_x-1)*N+_y);
         if (_x+1<N && b[_x+1][_y]>=a[i].first)
                unite(a[i].second,(_x+1)*N+_y);
         if (_y>0 && b[_x][_y-1]>=a[i].first)
                unite(a[i].second,_x*N+_y-1);
         if (_y+1<N && b[_x][_y+1]>=a[i].first)
                unite(a[i].second,_x*N+_y+1);
        }  
       while (j>0 )
              {
               int idx=tmp[j].second;
               if (find(I[idx].x1*N+I[idx].y1)==
                   find(I[idx].x2*N+I[idx].y2))
                 Sol[idx]+=k;
               --j;
               }   

      }
    for (i=1;i<=Q;++i)
      printf("%d\n",Sol[i]);
    return 0;
    }