제출 #1328296

#제출 시각아이디문제언어결과실행 시간메모리
1328296Zbyszek99Bitaro's Travel 2 (JOI25_travel2)C++20
100 / 100
396 ms57924 KiB
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define ff first
#define ss second
#define vl vector<long long>
#define vi vector<int>
#define pii pair<int,int>
#define pll pair<long long, long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace std;
//mt19937 mt;void random(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll rand(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = 1e9+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;

struct event
{
    int time,type,x,y;
    bool operator<(const event& other) const
    {
        if(time != other.time) return time < other.time;
        return type < other.type;
    }
};

int parent[300'005];
int parent_time[300'005];
pii max_val[300'005];
vi T[300'005];
int TV[300'005];
int subtree[300'005];
int jump[300'005][20];
bool odw[300'005];

pii find_(int v)
{
    if(parent[v] == -1)
    {
        return {v,0};
    }
    pii w = find_(parent[v]);
    return {w.ff,max(w.ss,parent_time[v])};
}

void union_(int a, int b,int t)
{
    pii p1 = find_(a);
    pii p2 = find_(b);
    if(subtree[p1.ff] > subtree[p2.ff]) swap(p1,p2);
    if(p1.ff == p2.ff)
    {
        return;
    }
    subtree[p2.ff] += subtree[p1.ff];
    parent[p1.ff] = p2.ff;
    parent_time[p1.ff] = t;
    max_val[p2.ff] = max(max_val[p1.ff],max_val[p2.ff]);
}

bool check(int a, int b, int t)
{
    int cur_a = a;
    odw[cur_a] = 1;
    while(parent[cur_a] != -1 && parent_time[cur_a] <= t)
    {
        cur_a = parent[cur_a];
        odw[cur_a] = 1;
    }
    bool is_ok = 0;
    int cur_b = b;
    if(odw[cur_b]) is_ok = 1;
    while(parent[cur_b] != -1 && parent_time[cur_b] <= t)
    {
        cur_b = parent[cur_b];
        if(odw[cur_b]) is_ok = 1;
    }
    cur_a = a;
    odw[cur_a] = 0;
    while(parent[cur_a] != -1 && parent_time[cur_a] <= t)
    {
        cur_a = parent[cur_a];
        odw[cur_a] = 0;
    }
    return is_ok;
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random();
    int n,m,L;
    cin >> n >> m >> L;
    rep(i,n) T[i].resize(m);
    rep(i,n) rep(j,m) cin >> T[i][j];
    rep(i,n) rep(j,m)
    {
        int v = i*m+j;
        TV[v] = T[i][j];
        parent[v] = -1;
        subtree[v] = 1;
        max_val[v] = {T[i][j],v};
    }
    vector<event> events;
    rep(i,n) rep(j,m)
    {
        events.pb({T[i][j],0,i,j});
        events.pb({T[i][j]+L,1,i,j});
    }
    sort(all(events));
    vector<pii> dir = {{-1,0},{1,0},{0,-1},{0,1}};
    forall(it,events)
    {
        if(it.type == 0)
        {
            forall(d,dir)
            {
                if(it.x + d.ff >= 0 && it.x + d.ff < n && it.y + d.ss >= 0 && it.y + d.ss < m && T[it.x+d.ff][it.y+d.ss] <= T[it.x][it.y])
                {
                    union_(it.x*m+it.y,(it.x+d.ff) * m + (it.y + d.ss),it.time);
                }
            }
        }
        else
        {
            pii p = find_(it.x * m + it.y);
            jump[it.x*m+ it.y][0] = max_val[p.ff].ss;
        }
    }
    rep2(bit,1,19)
    {
        rep(v,n*m)
        {
            jump[v][bit] = jump[jump[v][bit-1]][bit-1];
        }
    }
    int q;
    cin >> q;
    rep(i,q)
    {
        int a,b,c,d;
        cin >> a >> b >> c >> d;
        a--;
        b--;
        c--;
        d--;
        int v1 = a*m+b;
        int v2 = c*m+d;
        if(v1 == v2)
        {
            cout << "0\n";
            continue;
        }
        if(check(v1,v2,TV[v1]+L))
        {
            cout << "1\n";
            continue;
        }
        int ans = 0;
        if(!check(jump[v1][19],v2,TV[jump[v1][19]]+L))
        {
            cout << "-1\n";
            continue;
        }
        for(int bit = 18; bit >= 0; bit--)
        {
      //      cout << v1 << " " << v2 << " " << jump[v1][bit] << " " << bit << " jump\n";
            int new_v = jump[v1][bit];
            if(!check(new_v,v2,TV[new_v]+L))
            {
                ans += (1 << bit);
                v1 = new_v;
            }
        }
        cout << ans+2 << "\n";
    }
}
#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...