Cod sursa(job #2661634)

Utilizator Ioana_GaborGabor Ioana Ioana_Gabor Data 22 octombrie 2020 14:00:42
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.86 kb
#include <bits/stdc++.h>
#define NMAX 1000

using namespace std;

ifstream fi("pirati.in");
ofstream fo("pirati.out");

int n,m,q,cnta,cnti,x1,yy1,x2,yy2,le;
int mat[NMAX+5][NMAX+5],cod[NMAX+5][NMAX+5],viz[NMAX+5][NMAX+5];
vector<int> vecini[2*NMAX*NMAX+5];
vector<int> G[NMAX+5];
char ch;
int dx[]={-1,-1,-1,0,0,1,1,1};
int dy[]={-1,0,1,-1,1,-1,0,1};
int euler[2*NMAX*NMAX+5],L[2*NMAX*NMAX+5],ap[2*NMAX*NMAX+5];
int rmq[30][2*NMAX*NMAX+5],logg2[2*NMAX*NMAX+5];

void filll(int x,int y,int c){
    cod[x][y]=c;
    for(int i=0;i<8;i++){
        x2=x+dx[i];
        yy2=y+dy[i];
        if(cod[x2][yy2]==0&&mat[x2][yy2]==mat[x][y]){
            filll(x2,yy2,c);
        }
    }
}

int indice(int x){
    if(x<0){
        return 2*(-x);
    }else{
        return 2*x+1;
    }
}

void cauta_vecini(int x,int y,int c){
    viz[x][y]=1;
    for(int i=0;i<8;i++){
        x2=x+dx[i];
        yy2=y+dy[i];
        if(!viz[x2][yy2]){
            if(cod[x2][yy2]==c){
                cauta_vecini(x2,yy2,c);
            }else if(cod[x2][yy2]!=-NMAX*NMAX-5){
                vecini[indice(c)].push_back(indice(cod[x2][yy2]));
            }
        }
    }
}

void remove_duplicates(vector<int> &v){
    vector<int>::iterator it;
    sort(v.begin(),v.end());
    it=unique(v.begin(),v.end());
    v.resize(distance(v.begin(),it));
}

void read(){
    fi>>n>>m>>q;
    n+=2;
    m+=2;
    for(int i=2;i<=n-1;i++){
        for(int j=2;j<=m-1;j++){
            fi>>ch;
            mat[i][j]=ch-'0';
        }
    }
}

void get_tree(){
    for(int i=0;i<=m+1;i++){
        cod[0][i]=cod[n+1][i]=-NMAX*NMAX-5;
    }
    for(int i=0;i<=n+1;i++){
        cod[i][0]=cod[i][m+1]=-NMAX*NMAX-5;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(!cod[i][j]){
                if(!mat[i][j]){
                    ++cnta;
                    filll(i,j,cnta);
                }else{
                    ++cnti;
                    filll(i,j,-cnti);
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(!viz[i][j]){
                cauta_vecini(i,j,cod[i][j]);
            }
        }
    }
    int ind;
    for(int i=1;i<=cnta;i++){
        ind=indice(i);
        remove_duplicates(vecini[ind]);
    }
    for(int i=1;i<=cnti;i++){
        ind=indice(-i);
        remove_duplicates(vecini[ind]);
    }
    for(int i=1;i<=cnta;i++){
        ind=indice(i);
        for(int j=0;j<vecini[ind].size();j++){
            for(int jj=0;jj<vecini[vecini[ind][j]].size();jj++){
                if(vecini[vecini[ind][j]][jj]!=ind){
                    G[i].push_back(vecini[vecini[ind][j]][jj]/2);
                }
            }
        }
        remove_duplicates(G[i]);
    }

}

void dfs(int node, int level){
    euler[++le]=node;
    L[le]=level;
    ap[node]=le;
    for(int i=0;i<G[node].size();i++){
        dfs(G[node][i],level+1);
        euler[++le]=node;
        L[le]=level;
    }
}

void RMQ(){
    rmq[0][1]=1;
    for(int i=2;i<=le;i++){
        logg2[i]=logg2[i>>2]+1;
        rmq[0][i]=i;
    }
    for(int j=1;(1<<j)<=le;j++){
        for(int i=1;i+(1<<j)-1<=le;i++){
            if(L[rmq[j-1][i]]<=L[rmq[j-1][i+(1<<(j-1))]]){
                rmq[j][i]=rmq[j-1][i];
            }else{
                rmq[j][i]=rmq[j-1][i+(1<<(j-1))];
            }
        }
    }
}

int LCA(int n1,int n2){
    if(ap[n1]>ap[n2]){
        swap(n1,n2);
    }
    x1=ap[n1];
    x2=ap[n2];
    yy1=logg2[x2-x1+1];
    if(L[rmq[yy1][x1]]<L[rmq[yy1][x2-(1<<yy1)+1]]){
        return euler[rmq[yy1][x1]];
    }
    return euler[rmq[yy1][x2-(1<<yy1)+1]];
}

void solve(){
    dfs(1,1);
    RMQ();
    int n1,n2,lca;
    while(q--){
        fi>>x1>>yy1>>x2>>yy2;
        n1=cod[x1+1][yy1+1];
        n2=cod[x2+1][yy2+1];
        lca=LCA(n1,n2);
        fo<<(L[ap[n1]]+L[ap[n2]]-2*L[ap[lca]])<<'\n';
    }
}

int main(){
    read();
    get_tree();
    solve();
    fi.close();
    fo.close();
}