#include <bits/stdc++.h>
using namespace std;
const int LOG = 17;
int main(){
cin.tie(0)->sync_with_stdio(0);
int n, q;
cin >> n >> q;
vector<int> s(n), e(n);
vector<int> all;
for(int i = 0; i < n; ++i){
cin >> s[i] >> e[i];
all.push_back(s[i]);
all.push_back(e[i]);
}
// Coordinate compression
sort(all.begin(), all.end());
all.erase(unique(all.begin(), all.end()), all.end());
int m = all.size();
auto compress = [&](int x){
return int(lower_bound(all.begin(), all.end(), x) - all.begin());
};
// Sort events by end time
vector<int> order(n);
iota(order.begin(), order.end(), 0);
sort(order.begin(), order.end(), [&](int a, int b){
return e[a] < e[b];
});
vector<int> rank_(n);
for(int i = 0; i < n; ++i){
rank_[order[i]] = i;
}
// Segment tree: min start time for events ending at each position
vector<pair<int,int>> tree(4 * m, {INT_MAX, -1});
auto update = [&](auto& self, int v, int tl, int tr, int pos, int val, int idx) -> void {
if(tl == tr){
if(val < tree[v].first) tree[v] = {val, idx};
return;
}
int tm = (tl + tr) / 2;
if(pos <= tm) self(self, v*2, tl, tm, pos, val, idx);
else self(self, v*2+1, tm+1, tr, pos, val, idx);
tree[v] = min(tree[v*2], tree[v*2+1]);
};
auto query = [&](auto& self, int v, int tl, int tr, int l, int r) -> pair<int,int> {
if(l > r) return {INT_MAX, -1};
if(l == tl && r == tr) return tree[v];
int tm = (tl + tr) / 2;
return min(
self(self, v*2, tl, tm, l, min(r, tm)),
self(self, v*2+1, tm+1, tr, max(l, tm+1), r)
);
};
// prev[i][k] = event reached after 2^k backward jumps from i
vector<array<int, LOG>> prev(n);
for(int i = 0; i < n; ++i){
fill(prev[i].begin(), prev[i].end(), -1);
}
// Process events in order of end time
for(int i = 0; i < n; ++i){
int idx = order[i];
int si = compress(s[idx]);
int ei = compress(e[idx]);
// Find best predecessor: event with min start that can reach idx
auto [_, best] = query(query, 1, 0, m-1, si, ei);
prev[idx][0] = best;
// Add this event to segment tree
update(update, 1, 0, m-1, ei, s[idx], idx);
}
// Build binary lifting
for(int k = 1; k < LOG; ++k){
for(int i = 0; i < n; ++i){
if(prev[i][k-1] != -1){
prev[i][k] = prev[prev[i][k-1]][k-1];
}
}
}
// Helper: can we switch from event a to event b?
auto canSwitch = [&](int a, int b) -> bool {
return s[b] <= e[a] && e[a] <= e[b];
};
// Answer queries
while(q--){
int st, en;
cin >> st >> en;
--st; --en;
if(st == en){
cout << "0\n";
continue;
}
// en must end strictly after st (otherwise impossible)
if(rank_[en] <= rank_[st]){
cout << "impossible\n";
continue;
}
// Direct switch?
if(canSwitch(st, en)){
cout << "1\n";
continue;
}
// Binary lift backwards from en
// Find the earliest event (by rank) reachable from en that st can reach
int cur = en;
int ans = 0;
for(int k = LOG - 1; k >= 0; --k){
int nxt = prev[cur][k];
if(nxt != -1 && !canSwitch(st, nxt)){
cur = nxt;
ans += (1 << k);
}
}
// One more jump
if(prev[cur][0] != -1 && canSwitch(st, prev[cur][0])){
cout << ans + 2 << "\n";
} else {
cout << "impossible\n";
}
}
return 0;
}