Submission #1262479

#TimeUsernameProblemLanguageResultExecution timeMemory
1262479vlomaczkRailway Trip 2 (JOI22_ho_t4)C++20
87 / 100
261 ms57568 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

const int base = 1<<17;

struct min_left {
	vector<int> t;
	void construct() { t.assign(2*base, INT_MAX); }

	void update(int a, int b, int val) {
		if(a==b) {
			t[a+base] = min(t[a+base], val);
			return;
		}
		a += base-1;
		b += base+1;
		while(a/2 != b/2) {
			if(a%2==0) t[a+1] = min(t[a+1], val);
			if(b%2==1) t[b-1] = min(t[b-1], val);
			a/=2; b/=2;
		}
	}

	int query(int x) {
		int ans = INT_MAX;
		x += base;
		while(x > 0) {
			ans = min(ans, t[x]);
			x/=2;
		}
		return ans;
	}
};

struct max_right {
	vector<int> t;
	void construct() { t.assign(2*base, 0); }

	void update(int a, int b, int val) {
		if(a==b) {
			t[a+base] = max(t[a+base], val);
			return;
		}
		a += base-1;
		b += base+1;
		while(a/2 != b/2) {
			if(a%2==0) t[a+1] = max(t[a+1], val);
			if(b%2==1) t[b-1] = max(t[b-1], val);
			a/=2; b/=2;
		}
	}

	int query(int x) {
		int ans = 0;
		x += base;
		while(x > 0) {
			ans = max(ans, t[x]);
			x/=2;
		}
		return ans;
	}
};

struct sparse_table_max {
    vector<vector<pair<int,int>>> st;
    vector<int> log2;

    void construct(const vector<int> v) {
        int n = v.size();
        log2.assign(n + 1, 0);
        for (int i = 2; i <= n; i++) 
            log2[i] = log2[i/2] + 1;

        int K = log2[n] + 1;
        st.assign(n, vector<pair<int,int>>(K));

        for (int i = 0; i < n; i++)
            st[i][0] = {v[i], i};

        for (int j = 1; j < K; j++) {
            for (int i = 0; i + (1 << j) <= n; i++) {
                pair<int,int> left = st[i][j-1];
                pair<int,int> right = st[i + (1 << (j-1))][j-1];
                if (left.first >= right.first)
                    st[i][j] = left;
                else
                    st[i][j] = right;
            }
        }
    }

    pair<int,int> query(int a, int b) {
        int j = log2[b - a + 1];
        pair<int,int> left = st[a][j];
        pair<int,int> right = st[b - (1 << j) + 1][j];
        if (left.first >= right.first) return left;
        return right;
    }
};

struct sparse_table_min {
	sparse_table_max stm;

	void construct(vector<int> v) {
		for(auto &x : v) x*=-1;
		stm.construct(v);
	}

	pair<int, int> query(int a, int b) {
		pair<int, int> x = stm.query(a, b);
		x.first*=-1;
		return x;
	}
};

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	ll n, k;
	cin >> n >> k;
	min_left ml; ml.construct();
	max_right mr; mr.construct();
	for(int i=1; i<=n; ++i) {
		mr.update(i, i, i);
		ml.update(i, i, i);
	}
	int m;
	cin >> m;
	for(int i=0; i<m; ++i) {
		ll a, b;
		cin >> a >> b;
		if(a<b) {
			mr.update(a, min(a+k-1, b-1), b);
		} else {
			ml.update(max(a-k+1, b+1), a, b);
		}
	}
	vector<int> vml(n+1), vmr(n+1);
	for(int i=1; i<=n; ++i) {
		vml[i] = ml.query(i);
		vmr[i] = mr.query(i);
	}
	sparse_table_max stmax;
	sparse_table_min stmin;
	stmax.construct(vmr);
	stmin.construct(vml);
	//for(int i=1; i<=n; ++i) cout << vmr[i] << " "; cout << "\n";
	//for(int i=1; i<=n; ++i) cout << vml[i] << " "; cout << "\n";
	ll q;
	cin >> q;
	if(n*q <= 4'000'000) {
		while(q--) {
			int a, b;
			cin >> a >> b;
			int ans = 0;
			pair<int, int> curr = {a, a};
			pair<int, int> prev = {-1, -1};
			while(1) {
				if(curr.first == prev.first && curr.second == prev.second) break;
				if(curr.first <= b && b <= curr.second) break;
				prev = curr;
				curr.second = stmax.query(prev.first, prev.second).first;
				curr.first = stmin.query(prev.first, prev.second).first;
				ans++;
			}
			if(curr.first <= b && b <= curr.second) cout << ans << "\n";
			else cout << "-1\n";
		}
	} else {
		int maxlog = 16;
		vector<vector<int>> jumpR(n+1, vector<int>(maxlog+1)), jumpL(n+1, vector<int>(maxlog+1));
		for(int i=1; i<=n; ++i) {
			jumpR[i][0] = vmr[i];
			jumpL[i][0] = vml[i];		
		}
		for(int x=1; x<=maxlog; ++x) {
			for(int i=1; i<=n; ++i) {
				jumpL[i][x] = jumpL[stmin.query(jumpL[i][x-1], i).second][x-1];
				jumpR[i][x] = jumpR[stmax.query(i, jumpR[i][x-1]).second][x-1];
			}
		}
		while(q--) {
			int a, b;
			cin >> a >> b;
			if(a < b) {
				ll ans = 0;
				for(int i=maxlog; i>=0; --i) {
					if(jumpR[a][i] < b) {
						a = stmax.query(a, jumpR[a][i]).second;
						ans += 1LL<<i;
					}
				}
				if(b <= jumpR[a][0]) cout << ans+1 << "\n";
				else cout << "-1\n";
			} else {
				ll ans = 0;
				for(int i=maxlog; i>=0; --i) {
					if(jumpL[a][i] > b) {
						a = stmin.query(jumpL[a][i], a).second;
						ans += 1LL<<i;
					}
				}
				if(jumpL[a][0] <= b) cout << ans+1 << "\n";
				else cout << "-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...