제출 #1337493

#제출 시각아이디문제언어결과실행 시간메모리
1337493alexddBitaro's Travel 2 (JOI25_travel2)C++20
100 / 100
894 ms175504 KiB
#include <bits/stdc++.h>
using namespace std;
const int INF = 2e9;
int dx[4] = {-1,+1,0,0};
int dy[4] = {0,0,-1,+1};

int h,w,L,q;
vector<vector<int>> mat;

namespace DSU
{
    int father[300005], siz[300005];
    pair<int, pair<int,int>> mxm[300005];
    void init()
    {
        for(int i=1;i<=h*w;i++)
        {
            father[i] = i;
            siz[i] = 1;
        }
    }
    int get(int x)
    {
        if(father[x]!=x)
            father[x]=get(father[x]);
        return father[x];
    }
    void unite(int x, int y)
    {
        x = get(x);
        y = get(y);
        if(x == y)
            return;
        if(siz[x] < siz[y])
            swap(x, y);
        father[y] = x;
        siz[x] += siz[y];
        mxm[x] = max(mxm[x], mxm[y]);
    }
}
int getid(int x, int y)
{
    return (x-1) * w + y;
}

pair<int, pair<int,int>> nxt[300005][19];

vector<pair<int,pair<int,int>>> ord;
int qa[300005], qb[300005], qc[300005], qd[300005], lim[300005];

int who[300005];
vector<int> qrys[300005], comp[300005];
bool done[300005];
void uneste(int x, int y, int val)
{
    x = who[x];
    y = who[y];
    if(x == y)
        return;
    if(comp[x].size() + qrys[x].size() < comp[y].size() + qrys[y].size())
        swap(x, y);

    for(int qid:qrys[y])
    {
        if((who[getid(qa[qid],qb[qid])] == x && who[getid(qc[qid],qd[qid])] == y) || (who[getid(qa[qid],qb[qid])] == y && who[getid(qc[qid],qd[qid])] == x))
        {
            assert(lim[qid] == INF);
            lim[qid] = val;
            done[qid] = 1;
        }
        else if(!done[qid])
            qrys[x].push_back(qid);
    }
    for(int u:comp[y])
    {
        comp[x].push_back(u);
        who[u] = x;
    }
}

void calc_lim()
{
    for(int i=1;i<=q;i++)
    {
        qrys[getid(qa[i],qb[i])].push_back(i);
        qrys[getid(qc[i],qd[i])].push_back(i);
        lim[i] = INF;
    }
    for(int i=1;i<=h*w;i++)
    {
        who[i] = i;
        comp[i] = {i};
    }
    for(auto [val,poz]:ord)
    {
        int x = poz.first, y = poz.second;
        for(int v=0;v<4;v++)
        {
            int newx = x + dx[v], newy = y + dy[v];
            if(1<=newx && newx<=h && 1<=newy && newy<=w && mat[newx][newy] <= val)
            {
                uneste(getid(x,y), getid(newx,newy), val);
            }
        }
    }
}

signed main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);
    cin>>h>>w>>L;
    mat.resize(h+2, vector<int>(w+2,0));
    DSU::init();
    for(int i=1;i<=h;i++)
    {
        for(int j=1;j<=w;j++)
        {
            cin>>mat[i][j];
            ord.push_back({mat[i][j], {i,j}});
            DSU::mxm[getid(i,j)] = {mat[i][j], {i,j}};
        }
    }
    sort(ord.begin(), ord.end());
    int poz = -1;
    for(int i=0;i<ord.size();i++)
    {
        while(poz+1 < (int)ord.size() && ord[poz+1].first <= ord[i].first + L)
        {
            poz++;
            for(int v=0;v<4;v++)
            {
                int x = ord[poz].second.first + dx[v];
                int y = ord[poz].second.second + dy[v];
                if(1<=x && x<=h && 1<=y && y<=w && mat[x][y] <= ord[poz].first)
                    DSU::unite(getid(x,y), getid(ord[poz].second.first, ord[poz].second.second));
            }
        }
        assert(poz >= i);
        int myid = getid(ord[i].second.first, ord[i].second.second);
        nxt[myid][0] = DSU::mxm[DSU::get(myid)];
    }
    for(int p=1;p<19;p++)
        for(int i=1;i<=h*w;i++)
            nxt[i][p] = nxt[getid(nxt[i][p-1].second.first, nxt[i][p-1].second.second)][p-1];

    cin>>q;
    for(int i=1;i<=q;i++)
    {
        cin>>qa[i]>>qb[i]>>qc[i]>>qd[i];
    }
    calc_lim();
    for(int i=1;i<=q;i++)
    {
        int a = qa[i], b = qb[i];
        int rez = 0;
        for(int p=18;p>=0;p--)
        {
            if(nxt[getid(a,b)][p].first < lim[i])
            {
                tie(a,b) = nxt[getid(a,b)][p].second;
                rez += (1<<p);
            }
        }
        if(nxt[getid(a,b)][0].first < lim[i])
            cout<<-1<<"\n";
        else
            cout<<rez+1<<"\n";
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...