#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> //required
//#include <ext/pb_ds/tree_policy.hpp> //required

//using namespace __gnu_pbds; //required 
using namespace std;
//template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; 

// ordered_set <int> s;
// s.find_by_order(k); returns the (k+1)th smallest element
// s.order_of_key(k); returns the number of elements in s strictly less than k

#define pb               push_back
#define mp(x,y)          make_pair(x,y)
#define all(x)           x.begin(), x.end()
#define print(vec,l,r)   for(int i = l; i <= r; i++) cout << vec[i] <<" "; cout << endl;
#define input(vec,N)     for(int i = 0; i < (N); i++) cin >> vec[i];
#define leftmost_bit(x)  (63-__builtin_clzll(x))
#define rightmost_bit(x) __builtin_ctzll(x) // count trailing zeros
#define set_bits(x)      __builtin_popcountll(x) 
#define pow2(i)          (1LL << (i))
#define is_on(x, i)      ((x) & pow2(i)) // state of the ith bit in x
#define set_on(x, i)     ((x) | pow2(i)) // returns integer x with ith bit on
#define set_off(x, i)    ((x) & ~pow2(i)) // returns integer x with ith bit off

#ifdef LOCAL_DEBUG
	#define debug(...) logger(#__VA_ARGS__, __VA_ARGS__)
#else
	#define debug(...) ;
#endif
  
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// auto dist = uniform_int_distribution<int>(l, r);
// use int a = dist(rng) to get a random number between [l,r] inclusive
template<typename ...Args>
void logger(string vars, Args&&... values) {
    cerr << vars << " = ";
    string delim = "";
    (..., (cerr << delim << values, delim = ", "));
	cerr << endl;
}

typedef long long int ll;
typedef long double ld;

const int MOD = 1e9+7; // 998244353;
const int MX = 2e5+5;
const ll INF = 1e18; // not too close to LLONG_MAX
const ld PI = acos((ld)-1);
const ld EPS = 1e-8;
const int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1}; // for every grid problem!!

// highly risky #defines
#define int ll // disable when you want to make code a bit faster
#define endl '\n' // disable when dealing with interactive problems

typedef vector<int> vi;
typedef pair<int, int> pii;

class DSUF{
public:
	vector<int> dist, sz;
    vector<int> par;
    int distinct_comp;
    int N;
    
    DSUF(int n){
		N = n;
		distinct_comp = n;
		dist.resize(n);
		par.resize(n);
		sz.resize(n);
		
		for(int i = 0; i < N; i++){
			dist[i] = 0;
			par[i] = i;
			sz[i] = 1;
		}
	}
    
    int get_key(int k){
        if(k == par[k]) return k;
		return par[k] = get_key(par[k]);
    }
    
    void merge(int k1, int k2){
        int head_k1 = get_key(k1);
        int head_k2 = get_key(k2);
        
        if(head_k1 == head_k2) return;
        
        distinct_comp--;

		// I want to connect k1 to k2, so k2 should be bigger
		if(dist[head_k1] > dist[head_k2]) swap(head_k1, head_k2); // union by depth
		// if(sz[head_k1]   > sz[head_k2])   swap(head_k1, head_k2); // union by size
		
		// use one of the union heuristics, both are practically the same 
        
		if(dist[head_k1] == dist[head_k2]) dist[head_k2]++;
		sz[head_k2] += sz[head_k1];

		par[head_k1] = head_k2;
    }
    
    bool is_connected(int k1, int k2){
		return get_key(k1) == get_key(k2);
	}
};
// template ends here


void solve(){
	// code starts from here
	int N, Q, s, d;
	cin >> N >> Q >> s >> d;
	s--;

	vi ans(Q, -1);
	vector<vi> queries;
	vi vec(N);
	input(vec, N);

	for(int k ,dest, i = 0; i < Q; i++){
		cin >> dest >> k;
		dest--;
		queries.pb({k, dest, i});
	}

	sort(all(queries));
	DSUF dsu(N);
	priority_queue<vector<int>> pq;

	for(int i = 0; i < N; i++){
		int index = lower_bound(all(vec), vec[i] + d) - vec.begin();

		int l = index-1, r = index;
		if(index != N && vec[index] == vec[i] + d){
			dsu.merge(i, index);
			r++;
		} 	

		// debug(i, l, r);

		if(l > i) pq.push({-abs(d - abs(vec[i]- vec[l])),  i, l, -1});
		if(r != N) pq.push({-abs(d - abs(vec[i]- vec[r])), i, r, +1});
	}

	// int l, r, add;
	
	for(vi query: queries){
		int k = query[0], dest = query[1], id = query[2];
		// debug(id);

		while(!pq.empty() && -pq.top()[0] <= k){
			vi temp = pq.top();
			pq.pop();
			
			int i = temp[1] , index = temp[2], add = temp[3];
			dsu.merge(i, index);

			// debug(-temp[0], i, index, add);

			if(i < index + add && index + add < N){
				if(dsu.is_connected(i, index+add) == false)
				pq.push({-abs(d - abs(vec[i] - vec[index+add])), i, index+add, add});
			}
		}
		// cerr << endl;

		if(dsu.is_connected(s, dest)) ans[id] = 1;
	}
	for(int i: ans){
		if(i == 1) cout << "Yes" << endl;
		else cout << "No" << endl;
	}
}


clock_t startTime;
double getCurrentTime() {
	return (double)(clock() - startTime) / CLOCKS_PER_SEC;
}

signed main(){
 	ios_base::sync_with_stdio(false);
    cin.tie(NULL);
	//startTime = clock();
	// mt19937_64 rnd(time(NULL));

	int T = 1;
	// cin >> T;

	while(T--){
		solve();
	}
	
	//cerr << getCurrentTime() << endl;
	return 0;
}
