Cod sursa(job #2403185)

Utilizator nikolapesic2802Nikola Pesic nikolapesic2802 Data 11 aprilie 2019 12:38:26
Problema Matrice 2 Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.46 kb
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define pb push_back
#define sz(x) (int)(x).size()
#define mp make_pair
#define f first
#define s second
#define all(x) x.begin(), x.end()
#define D(x) cerr << #x << " is " << (x) << "\n";

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; ///find_by_order(),order_of_key()
template<class T1, class T2> ostream& operator<<(ostream& os, const pair<T1,T2>& a) { os << '{' << a.f << ", " << a.s << '}'; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> ostream& operator<<(ostream& os, const map<T1,T2>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}

const int N=300*300+1;
struct node{
    int l,r,le,ri,val;
};
vector<node> tre;
int copyNode(int i)
{
    node ne{tre[i].l,tre[i].r,tre[i].le,tre[i].ri,tre[i].val};
    tre.pb(ne);
    return tre.size()-1;
}
int build(int l=0,int r=N-1)
{
    node ne{l,r,-1,-1,-1};
    if(l==r)
    {
        ne.val=l;
        tre.pb(ne);
        return tre.size()-1;
    }
    int m=(l+r)>>1;
    ne.le=build(l,m);
    ne.ri=build(m+1,r);
    tre.pb(ne);
    return tre.size()-1;
}
int root;
int sett(int pos,int val,int tr=root)
{
    if(pos<tre[tr].l||pos>tre[tr].r)
        return tr;
    int ne=copyNode(tr);
    if(tre[ne].l==pos&&tre[ne].r==pos)
    {
        tre[ne].val=val;
        return ne;
    }
    tre[ne].le=sett(pos,val,tre[ne].le);
    tre[ne].ri=sett(pos,val,tre[ne].ri);
    return ne;
}
int get(int pos,int tr=root)
{
    if(pos<tre[tr].l||pos>tre[tr].r)
        return 0;
    if(tre[tr].l==pos&&tre[tr].r==pos)
        return tre[tr].val;
    return get(pos,tre[tr].le)+get(pos,tre[tr].ri);
}
int find(int a,int tr,bool change=false)
{
    int p=get(a,tr);
    if(p==a)
        return a;
    int b=find(p,tr,change);
    if(change)
        root=sett(a,b);
    return b;
}
void merge(int a,int b)
{
    a=find(a,root,true);
    b=find(b,root,true);
    if(a==b)
        return;
    root=sett(a,b);
}
int n;
int convert(int a,int b)
{
    return a*n+b;
}
bool inside(int x,int y)
{
    return x>=0&&x<n&&y>=0&&y<n;
}
vector<int> dx={1,-1,0,0},dy={0,0,1,-1};
int main()
{
    FILE *in=fopen("matrice2.in","r"),*out=fopen("matrice2.out","w");
	int q;
	fscanf(in,"%i %i",&n,&q);
	vector<int> vals;
	vector<pair<int,pair<int,int> > > mat;
	vector<int> order;
	for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            int m;
            fscanf(in,"%i",&m);
            mat.pb({m,{i,j}});
            vals.pb(m);
            order.pb(m);
        }
    root=build();
    sort(all(vals));
    sort(all(mat));
    vals.erase(unique(all(vals)),vals.end());
    reverse(all(vals));
    reverse(all(mat));
    int m=vals.size();
    vector<int> kojiroot(m);
    int tr=0;
    for(int i=0;i<m;i++)
    {
        while(tr<(int)mat.size()&&mat[tr].f==vals[i])
        {
            int x=mat[tr].s.f,y=mat[tr].s.s;
            for(int k=0;k<4;k++)
            {
                int xx=x+dx[k],yy=y+dy[k];
                if(inside(xx,yy)&&order[convert(xx,yy)]>=mat[tr].f)
                    merge(convert(xx,yy),convert(x,y));
            }
            tr++;
        }
        kojiroot[i]=root;
    }
    for(int i=0;i<q;i++)
    {
        int x1,y1,x2,y2;
        fscanf(in,"%i %i %i %i",&x1,&y1,&x2,&y2);
        x1--;y1--;x2--;y2--;
        int a=convert(x1,y1),b=convert(x2,y2);
        int l=0,r=m-1;
        while(l<r)
        {
            int mm=(l+r)>>1;
            if(find(a,kojiroot[mm])==find(b,kojiroot[mm]))
                r=mm;
            else
                l=mm+1;
        }
        fprintf(out,"%i\n",vals[l]);
    }
    return 0;
}