//cre:gpt fix
#include<bits/stdc++.h>
#include<algorithm>
#include<random>
#include<chrono>
#include<cstdlib>
#include<ctime>
#include<numeric>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<queue>
#include<iomanip>
#define int long long
#define ll long long
#define L LLONG_MAX
#define fi first
#define se second
#define pii pair<int,int>
#define sz(a) ((int)a.size())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define REP(i,k,j) for(int i=k;i>=j;i--)
#define FORD(i,a) for(auto i:a)
#define rngdcl mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(l,r) ((l)+(rng()%(r-l+1)))
using namespace std;
const int nmax=5e4+69;
int n,m,k,q;
vector<pii> adj[nmax];
vector<pii> rev[nmax];
int suf[17][nmax][6],pfx[17][nmax][6];
void input()
{
    cin >> k >> n >> m >> q;
    FOR(i,1,m)
    {
        int u,v,w; cin >> u >> v >> w;
        u++; v++;
        if(u>=1 && u<=n && v>=1 && v<=n){
            adj[u].push_back({v,w});
            rev[v].push_back({u,w});
        }
    }
}
pii pos(int x)
{
    return {(x-1)/k+1,(x-1)%k+1};
}
void dnc(int l,int r,int lv)
{
    if(l>=r) return;
    pii pl = pos(l), pr = pos(r);
    if(pl.fi == pr.fi) return;
    int blockL = pl.fi, blockR = pr.fi;
    int midBlock = (blockL + blockR) / 2;
    int sl = (midBlock - 1) * k + 1;
    int sr = min(n, midBlock * k);
    int tl = sr + 1;
    int tr = min(n, (midBlock + 1) * k);
    FOR(u, l, sr) FOR(c,1,k) suf[lv][u][c] = L;
    FOR(v, tl, r) FOR(c,1,k) pfx[lv][v][c] = L;
    if(tl <= r && sl <= sr){
        int lenMid = sr - sl + 1;
        int lenNext = tr - tl + 1;
        vector<vector<ll>> E(lenMid, vector<ll>(lenNext, (ll)L));
        for(int a = 0; a < lenMid; ++a){
            int u = sl + a;
            FORD(e, adj[u]){
                int v = e.fi; int w = e.se;
                if(v >= tl && v <= tr){
                    int c = v - tl;
                    if((ll)w < E[a][c]) E[a][c] = w;
                }
            }
        }
        for(int a = 0; a < lenMid; ++a){
            int u = sl + a;
            for(int c = 0; c < lenNext; ++c){
                if(E[a][c] != (ll)L) suf[lv][u][c+1] = (int)E[a][c];
            }
        }
        for(int b = midBlock - 1; b >= blockL; --b){
            int start = (b - 1) * k + 1;
            int endd = min(n, b * k);
            for(int u = endd; u >= start; --u){
                FORD(e, adj[u]){
                    int v = e.fi; int w = e.se;
                    int vb = (v-1)/k + 1;
                    if(vb != b+1) continue;
                    for(int c = 1; c <= k; ++c){
                        if(suf[lv][v][c] == L) continue;
                        ll cand = (ll)w + (ll)suf[lv][v][c];
                        if(cand < (ll)L && cand < (ll)suf[lv][u][c]) suf[lv][u][c] = (int)cand;
                    }
                }
            }
        }
        for(int v = tl; v <= tr; ++v){
            for(int c = 1; c <= k; ++c) pfx[lv][v][c] = L;
            int offset = v - tl + 1;
            if(offset >=1 && offset <= lenNext) pfx[lv][v][offset] = 0;
        }
        int blockOfR = pos(r).fi;
        for(int b = midBlock + 1; b <= blockOfR; ++b){
            int start = (b - 1) * k + 1;
            int endd = min(n, b * k);
            if(b == blockOfR) break;
            int nextStart = b * k + 1;
            int nextEnd = min(n, (b+1) * k);
            for(int u = start; u <= endd; ++u){
                FORD(e, adj[u]){
                    int v = e.fi; int w = e.se;
                    int vb = (v-1)/k + 1;
                    if(vb != b+1) continue;
                    for(int c = 1; c <= k; ++c){
                        if(pfx[lv][u][c] == L) continue;
                        ll cand = (ll)pfx[lv][u][c] + (ll)w;
                        if(cand < (ll)L && cand < (ll)pfx[lv][v][c]) pfx[lv][v][c] = (int)cand;
                    }
                }
            }
        }
    }
    dnc(l, sr, lv+1);
    dnc(sr+1, r, lv+1);
}
pii find_node(int l,int r,int lv,int lf,int rt)
{
    pii pl = pos(l), pr = pos(r);
    int blockL = pl.fi, blockR = pr.fi;
    if(blockL == blockR) return {-1,-1};
    int midBlock = (blockL + blockR) / 2;
    int sr = min(n, midBlock * k);
    int tl = sr + 1;
    if(lf <= sr && rt >= tl) return {lv, sr};
    if(rt <= sr) return find_node(l, sr, lv+1, lf, rt);
    else return find_node(sr+1, r, lv+1, lf, rt);
}
void solve()
{
    FOR(i,0,16) FOR(j,1,n) FOR(x,1,5)
    {
        suf[i][j][x]=L;
        pfx[i][j][x]=L;
    }
    dnc(1,n,1);
    
    while(q--)
    {
        int l,r; cin >> l >> r;
        l++; r++;
        pii save=find_node(1,n,1,l,r);
        int mid=save.se;
        int lv=save.fi;
        int ans=L;
        if(pos(l).fi+1==pos(r).fi)
        {
            FORD(i,adj[l]) if(i.fi==r) ans=i.se;
        }
        else
        {
            if(lv==-1){ cout << -1 << '\n'; continue; }
            int midBlock = mid / k;
            int tl = mid + 1;
            int tr = min(n, (midBlock+1)*k);
            int lenNext = tr - tl + 1;
            FOR(c,1,lenNext) {
                if(suf[lv][l][c]!=L && pfx[lv][r][c]!=L){
                    ll cand = (ll)suf[lv][l][c] + (ll)pfx[lv][r][c];
                    if(cand < (ll)ans) ans = (int)cand;
                }
            }
        }
        if(ans==L) cout << -1 << '\n';
        else cout << ans << '\n';
    }
}
signed main()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    input();
    solve();
    return 0;
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |