Submission #1141113

#TimeUsernameProblemLanguageResultExecution timeMemory
1141113ackhavaRailway Trip 2 (JOI22_ho_t4)C++20
0 / 100
2105 ms440736 KiB
#include <bits/stdc++.h>
#define REP(v, i, j) for (int v = i; v != j; v++)
#define FORI(v) for (auto i : v)
#define FORJ(v) for (auto j : v)

#define OUT(v, a) \
    FORI(v)       \
    cout << i << a;
#define OUTS(v, a, b)      \
    cout << v.size() << a; \
    OUT(v, b)
#define in(a, n) \
    REP(i, 0, n) \
    cin >> a[i];

#define SORT(v) sort(begin(v), end(v))
#define REV(v) reverse(begin(v), end(v))
#define MEMSET(m) memset(m, -1, sizeof m)

#define pb push_back
#define fi first
#define se second

#define detachIO                      \
    ios_base::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0);
    
using namespace std;

template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
bool operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) {
    if(__x.size() != __y.size()) return false;
    return std::equal(__x.begin(), __x.end(), __y.begin());
}


typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef pair<pii, pii> piiii;

const int MOD = 1e9+7;

struct modint {
    long long val;

    modint() = default;
    modint(int _val): val(_val){}
    modint operator+(modint b){ return ((this->val + b.val)%MOD); }
    modint operator-(modint b){ return ((MOD + this->val - b.val)%MOD); }
    modint operator*(modint b){ return ((this->val * b.val)%MOD); }
    modint operator^(int a){
        if(a==0)return 1;
        if(a==1)return *this;
        return (((*this)*(*this))^(a>>1))*((*this)^(a&1)); 
    }
};

modint invert(modint a){
    return a^(MOD-2);
}

modint operator/(modint a, modint b){
    return a*invert(b);
}

namespace fwd {        
    struct segment_tree {
        long long n;
        typedef pii T;
        vector<T> seg;
        const T e = {-1,0};

        T merge(T a, T b){
            if(b==e)return a;
            if(a.fi > b.fi)return a;
            return b;
        }

        segment_tree(long long _n): n(_n),seg(4*_n+10,e) /** BUG: GCC does not initialize the elements properly this way */ {
            for(auto &i:seg)i=e;
        }

        void update(long long pos, long long l, long long r, long long idx, T val){
            if(r<idx)return;
            if(l>idx)return;
            if(l==r){
                seg[pos]=val;
                return;
            }
            update(pos*2+1,l,(l+r)/2,idx,val);
            update(pos*2+2,((l+r)/2)+1,r,idx,val);
            seg[pos]=merge(seg[pos*2+1],seg[pos*2+2]);
        }

        T query(long long pos, long long l, long long r, long long ql, long long qr){
            if(l > qr)return e;
            if(ql > r)return e;
            if(ql <= l && r <= qr)return seg[pos];
            if(l==r)return e;
            return merge(query(pos*2+1,l,(l+r)/2,ql,qr),query(pos*2+2,((l+r)/2)+1,r,ql,qr));
        }
    };

    int n,m,k;
    int r[200100];
    int j[200100];
    int b[200100][30];
    vector<pii> s[200100];
    vector<pii> e[200100];
    map<pii,int> mp;

    void init(int _n, int _m, int _k){
        n=_n,m=_m,k=_k;
    }

    void add_edge(int a, int b, int i){
        assert(a<b);
        s[a].pb({b,i});
        e[min(b+1,a+k)].pb({b,i});
    }

    void compute(){
        set<pii> st;
        segment_tree tree(n+10);
        REP(i,1,n+1){
            FORJ(s[i])st.insert(j);
            FORJ(e[i])st.erase(j);
            r[i]=i;
            if(st.size())r[i]=st.rbegin()->fi;
            // cerr<<r[i]<<" ";
            tree.update(0,0,n,i-1,{r[i],i});
        }
        // cerr<<endl;
        REP(i,1,n+1){
            j[i]=b[i][0]=tree.query(0,0,n,i-1,r[i]-1).se;
            // cerr<<j[i]<<" ";
        }
        REP(x,1,25){
            REP(i,1,n+1){
                b[i][x]=b[b[i][x-1]][x-1];
            }
        }
    }

    int query(int s, int t){
        if(mp.count({s,t}))return mp[{s,t}];
        int s0=s;
        int ans=0;
        REP(xx,0,25){
            int x=24-xx;
            if(r[s]>=t)break;
            if(r[b[s][x]]<t)s=b[s][x],ans+=(1<<x);
        }
        while(r[s]<t){
            s=j[s],ans++;
            if(j[s]==s)break;
        }
        ans++;
        if(r[s]<t)ans=-1;
        // return ans;
        return mp[{s0,t}]=ans;
    }
}

namespace bwd {        
    struct segment_tree {
        long long n;
        typedef pii T;
        vector<T> seg;
        const T e = {-1,0};

        T merge(T a, T b){
            if(b==e)return a;
            if(a.fi > b.fi)return a;
            return b;
        }

        segment_tree(long long _n): n(_n),seg(4*_n+10,e) /** BUG: GCC does not initialize the elements properly this way */ {
            for(auto &i:seg)i=e;
        }

        void update(long long pos, long long l, long long r, long long idx, T val){
            if(r<idx)return;
            if(l>idx)return;
            if(l==r){
                seg[pos]=val;
                return;
            }
            update(pos*2+1,l,(l+r)/2,idx,val);
            update(pos*2+2,((l+r)/2)+1,r,idx,val);
            seg[pos]=merge(seg[pos*2+1],seg[pos*2+2]);
        }

        T query(long long pos, long long l, long long r, long long ql, long long qr){
            if(l > qr)return e;
            if(ql > r)return e;
            if(ql <= l && r <= qr)return seg[pos];
            if(l==r)return e;
            return merge(query(pos*2+1,l,(l+r)/2,ql,qr),query(pos*2+2,((l+r)/2)+1,r,ql,qr));
        }
    };

    int n,m,k;
    int r[200100];
    int j[200100];
    int b[200100][30];
    vector<pii> s[200100];
    vector<pii> e[200100];
    map<pii,int> mp;

    void init(int _n, int _m, int _k){
        n=_n,m=_m,k=_k;
    }

    void add_edge(int a, int b, int i){
        assert(a<b);
        s[a].pb({b,i});
        e[min(b+1,a+k)].pb({b,i});
    }

    void compute(){
        set<pii> st;
        segment_tree tree(n+10);
        REP(i,1,n+1){
            FORJ(s[i])st.insert(j);
            FORJ(e[i])st.erase(j);
            r[i]=i;
            if(st.size())r[i]=st.rbegin()->fi;
            // cerr<<r[i]<<" ";
            tree.update(0,0,n,i-1,{r[i],i});
        }
        // cerr<<endl;
        REP(i,1,n+1){
            j[i]=b[i][0]=tree.query(0,0,n,i-1,r[i]-1).se;
            // cerr<<j[i]<<" ";
        }
        REP(x,1,25){
            REP(i,1,n+1){
                b[i][x]=b[b[i][x-1]][x-1];
            }
        }
    }

    int query(int s, int t){
        if(mp.count({s,t}))return mp[{s,t}];
        int s0=s;
        int ans=0;
        REP(xx,0,25){
            int x=24-xx;
            if(r[s]>=t)break;
            if(r[b[s][x]]<t)s=b[s][x],ans+=(1<<x);
        }
        while(r[s]<t){
            s=j[s],ans++;
            if(j[s]==s)break;
        }
        ans++;
        if(r[s]<t)ans=-1;
        // return ans;
        return mp[{s0,t}]=ans;
    }
}

int main(){
    detachIO;
    int n,m,k;cin>>n>>k>>m;
    fwd::init(n,m,k);
    bwd::init(n,m,k);
    REP(i,0,m){
        int a,b;cin>>a>>b;
        if(a<b)fwd::add_edge(a,b,i);
        else bwd::add_edge(n+1-a,n+1-b,i);
    }
    fwd::compute();
    bwd::compute();
    int q;cin>>q;
    // cerr<<q<<endl;
    while(q--){
        int s,t;cin>>s>>t;
        int ans=-1;
        if(s<t){
            REP(i,1,s+1){
                int c1,c2;
                c1=c2=0;
                if(s!=i)c1=(bwd::query(n+1-s,n+1-i));
                c2=fwd::query(i,t);
                if(c1==-1)continue;
                if(c2==-1)continue;
                if(ans!=-1)ans=min(ans,c1+c2);
                else ans=c1+c2;
            }
        } else {
            REP(i,s,n+1){
                int c1,c2;
                c1=c2=0;
                if(s!=i)c1=(fwd::query(s,i));
                c2=bwd::query(n+1-i,n+1-t);
                if(c1==-1)continue;
                if(c2==-1)continue;
                if(ans!=-1)ans=min(ans,c1+c2);
                else ans=c1+c2;
            }
        }
        cout<<ans<<'\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...