#include <bits/stdc++.h>
#include <cassert>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define rrep(i, a, b) for(int i = b-1; i >= (a); --i)
#define trav(a,x) for (auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

struct UF {
	vi e;
	UF(int n) : e(n, -1) {}
	bool sameSet(int a, int b) { return find(a) == find(b); }
	int size(int x) { return -e[find(x)]; }
	int find(int x) { return e[x] < 0 ? x : e[x] = find(e[x]); }
	bool join(int a, int b) {
		a = find(a), b = find(b);
		if (a == b) return false;
		if (e[a] > e[b]) swap(a, b);
		e[a] += e[b]; e[b] = a;
		return true;
	}
};

int N, numag, myid, maxlen;

[[noreturn]]
void halt() {
	cout << "halt" << endl;
	exit(0);
}

bool query(int r, int c) {
	r++, c++;
	cout << "? " << r << " " << c << endl;
	int ret;
	cin >> ret;
	assert(cin);
	return (bool)ret;
}

bool query2(int r, int c) {
	if (r % 2 && c % 2) return false;
	if (r % 2 == 0 && c % 2 == 0) return true;
	r = min(r, N-1);
	c = min(c, N-1);
	return query(r, c);
}

void send(int to, string what) {
	cout << "> " << to << " " << what << endl;
	cin >> what;
	assert(what == "OK");
}

void noop() {
	cout << "." << endl;
	string what;
	cin >> what;
	assert(what == "OK");
}

pair<int, string> receive(int from) {
	string what;
	if (from == -1)
		cout << "< " << '?' << endl;
	else
		cout << "< " << from << endl;
	char c;
	cin >> c;
	if (c == '-') {
		char c;
		cin >> c;
		assert(c == '-');
		// cin >> c;
		return {-1, ""};
	}
	cin.unget();
	cin >> from;
	assert(cin);
	cin.ignore();
	getline(cin, what);
	return {from, what};
}

string msg0;
string recvmulti(int ag) {
	if (ag == 0 && myid == 0) return msg0;
	auto pa = receive(ag);
	while (pa.first == -1)
		pa = receive(ag);
	string s = pa.second;
	while (s.back() == 0x21) {
		pa = receive(ag);
		assert(pa.first != -1);
		s.pop_back();
		s += pa.second;
	}
	return s;
}

void sendmulti(int ag, string s) {
	if (ag == 0 && myid == 0) {
		msg0 = s;
		return;
	}

	while (sz(s) > maxlen) {
		string s2 = s.substr(0, maxlen-1);
		s2 += (char)0x21;
		send(ag, s2);
		s = s.substr(maxlen-1);
	}
	send(ag, s);
}

string decode(string s) { return s; }
const string OR = "DLUR";
const int DY[4] = {1,0,-1,0};
const int DX[4] = {0,-1,0,1};

int main() {
	cin.tie(0)->sync_with_stdio(0);
	// cin.exceptions(cin.failbit);
	cin >> N >> numag >> myid >> maxlen;
	int nw = (int)sqrt(numag); // num tiles, w
	int nh = numag / nw;

	int w = (N + nw-1) / nw;
	if (w%2) w++;
	int h = (N + nh-1) / nh;
	if (h%2) h++;

	if (myid >= nh*nw) {
		halt();
	}
	numag = nh*nw;

	if (0 && myid == 0) {
		cerr << "w = " << w << endl;
		cerr << "h = " << h << endl;
	}

	int myi = myid / nw;
	int myj = myid % nw;
	vector<vi> grid(h, vi(w));
	rep(i,0,h) rep(j,0,w) {
		int p = query2(myi * h + i, myj * w + j);
		grid[i][j] = p;
	}

	auto ide = [&](int i, int j) { return (i + 1) * (w + 2) + (j + 1); };

	UF uf((w+2)*(h+2));
	rep(i,0,h) rep(j,0,w-1) if (grid[i][j] && grid[i][j+1]) uf.join(ide(i,j), ide(i,j+1));
	rep(i,0,h-1) rep(j,0,w) if (grid[i][j] && grid[i+1][j]) uf.join(ide(i,j), ide(i+1,j));
	rep(i,0,h) if (grid[i][0]) uf.join(ide(i,0), ide(i,-1));
	rep(i,0,h) if (grid[i][w-1]) uf.join(ide(i,w-1), ide(i,w));
	rep(j,0,w) if (grid[0][j]) uf.join(ide(0,j), ide(-1,j));
	rep(j,0,w) if (grid[h-1][j]) uf.join(ide(h-1,j), ide(h,j));

	vi comps;
	rep(i,0,h) comps.push_back(ide(i,-1));
	rep(j,0,w) comps.push_back(ide(h,j));
	rrep(i,0,h) comps.push_back(ide(i,w));
	rrep(j,0,w) comps.push_back(ide(-1,j));
	trav(a,comps) a = uf.find(a);

	vi lasts((w+2)*(h+2), -1);
	vi firsts((w+2)*(h+2), -1);
	rep(i,0,sz(comps)) lasts[comps[i]] = i;
	rrep(i,0,sz(comps)) firsts[comps[i]] = i;

	vi out;
	vi st;
	rep(i,0,sz(comps)) {
		int bits = 0;
		if (firsts[comps[i]] == i) {
			bits |= 1;
			st.push_back(comps[i]);
		}

		if (lasts[comps[i]] == i) {
			bits |= 2;
			assert(st.back() == comps[i]);
			st.pop_back();
		}
		out.push_back(bits);
	}

	string sendstr;
	for (int i = 0; i < sz(out); i += 3) {
		int a = out[i];
		int b = i+1 < sz(out) ? out[i+1] : 0;
		int c = i+2 < sz(out) ? out[i+2] : 0;
		int x = a | b << 2 | c << 4;
		sendstr += (char)(0x21 + x);
	}

	auto process = [&]() {
		string s = recvmulti(0);
		istringstream iss(s);
		int a, b;
		string resp;
		while (iss >> a >> b) {
			string path;

			auto conv = [&](int ind) {
				pii start;
				if (ind < h) path += 'R', start = {ind, 0};
				else {
					ind -= h;
					if (ind < w) path += 'U', start = {h-1, ind};
					else {
						ind -= w;
						if (ind < h) path += 'L', start = {h-1 - ind, w-1};
						else {
							ind -= h;
							if (ind < w) path += 'D', start = {0, w-1 - ind};
							else assert(0);
						}
					}
				}
				return start;
			};

			pii start = conv(a);
			pii end = conv(b);
			path.pop_back();

			assert(grid[start.first][start.second]);

			vector<pii> q = {start};
			vector<vi> seen(h, vi(w));
			seen[start.first][start.second] = 1;
			vector<vector<char>> bt(h, vector<char>(w, -1));
			vector<vector<pii>> bt2(h, vector<pii>(w));
			rep(i,0,sz(q)) {
				auto pa = q[i];
				rep(di,0,4) {
					int ni = pa.first + DY[di];
					int nj = pa.second + DX[di];
					if (ni < 0 || nj < 0 || ni >= h || nj >= w) continue;
					if (seen[ni][nj]) continue;
					if (!grid[ni][nj]) continue;
					seen[ni][nj] = 1;
					bt[ni][nj] = OR[di];
					bt2[ni][nj] = pa;
					q.push_back({ni, nj});
				}
			}

			assert(seen[end.first][end.second]);

			string path2;
			auto cur = end;
			while (cur != start) {
				path2 += bt[cur.first][cur.second];
				cur = bt2[cur.first][cur.second];
			}
			reverse(all(path2));
			path += path2;

			// cerr << myid << " from " << start.first << ' ' << start.second << " to " << end.first << ' ' << end.second << " walk " << path << endl;

			resp += path;
			resp += (char)0x22;
		}
		sendmulti(0, resp);
	};

	if (myid > 0) {
		send(0, sendstr);

		process();
	} else {
		noop();

		int HOR_BASE = 0, HOR_COUNT = w * nw * (h * nh + 1);
		int VERT_BASE = HOR_COUNT, VERT_COUNT = (w * nw + 1) * h * nh;
		int nnodes = HOR_COUNT + VERT_COUNT;
		vector<vector<tuple<int, int, int, int>>> edges(nnodes);

		rep(ag,0,numag) {
			int itsi = ag / nw;
			int itsj = ag % nw;
			string s = sendstr;
			if (ag != 0) {
				auto pa = receive(ag);
				assert(pa.first != -1);
				s = pa.second;
			}
			vi out;
			for (char ch : s) {
				int x = ch - 0x21;
				int a = x & 3;
				int b = x >> 2 & 3;
				int c = x >> 4 & 3;
				out.push_back(a);
				out.push_back(b);
				out.push_back(c);
			}
			out.resize(sz(comps));
			assert(sz(comps) == 2*(h+w));
			auto hor = [&](int ind, int add) {
				return HOR_BASE + (itsi + add) * h * w * nw + (itsj * w + ind);
			};
			auto vert = [&](int ind, int add) {
				return VERT_BASE + (itsi * h + ind) * (w * nw + 1) + (itsj + add) * w;
			};
			auto tr = [&](int ind) {
				if (ind < h) return vert(ind, 0);
				ind -= h;
				if (ind < w) return hor(ind, 1);
				ind -= w;
				if (ind < h) return vert(h-1 - ind, 1);
				ind -= h;
				if (ind < w) return hor(w-1 - ind, 0);
				assert(0);
			};
			vector<vi> st;
			rep(j,0,sz(out)) {
				if (out[j] & 1) {
					st.push_back(vi());
				}
				st.back().push_back(j);
				if (out[j] & 2) {
					vi comp = st.back();
					rep(k,0,sz(comp)) rep(l,k+1,sz(comp)) {
						int a = comp[k];
						int b = comp[l];
						edges[tr(a)].push_back({tr(b), ag, a, b});
						edges[tr(b)].push_back({tr(a), ag, b, a});
					}
					st.pop_back();
				}
			}
			assert(st.empty());
		}

		vi q = {0};
		vi seen(nnodes);
		seen[0] = 1;
		vector<tuple<int,int,int,int>> bt(nnodes);
		rep(i,0,sz(q)) {
			int x = q[i];
			trav(ed, edges[x]) {
				auto& [y, a,b,c] = ed;
				if (!seen[y]) {
					q.push_back(y);
					seen[y] = 1;
					bt[y] = {x,a,b,c};
				}
			}
		}

		int last = HOR_COUNT - 2;
		assert(seen[last]);

		int at = last;
		vector<vector<pii>> ask(numag);
		vector<vector<string>> resps(numag);
		while (at != 0) {
			auto& [x,a,b,c] = bt[at];
			at = x;
			ask[a].push_back({b,c});
		}

		bool any = 0;
		rep(ag,0,numag) if (!ask[ag].empty()) {
			string s;
			trav(pa, ask[ag]) {
				s += to_string(pa.first);
				s += ' ';
				s += to_string(pa.second);
				s += ' ';
			}
			sendmulti(ag, s);
			if (ag != 0) any = 1;
		}

		if (!any) noop();

		process();

		rep(ag,0,numag) if (!ask[ag].empty()) {
			string s = recvmulti(ag);
			vector<string>& r = resps[ag];
			while (!s.empty()) {
				auto it = s.find((char)0x22);
				assert(it != string::npos);
				r.push_back(decode(s.substr(0, it)));
				s = s.substr(it + 1);
			}
			reverse(all(r));
		}

		at = last;
		vector<string> outpath;
		while (at != 0) {
			auto& [x,a,b,c] = bt[at];
			at = x;
			string s = resps[a].back();
			resps[a].pop_back();
			outpath.push_back(s);
		}
		reverse(all(outpath));

		string outpaths;
		trav(s, outpath)
			outpaths += s;
		outpaths = outpaths.substr(1); // skip entry

		int i = 0, j = 0;
		string outpath2;
		trav(ch, outpaths) {
			if (ch == 'R') {
				if (j < N-1) outpath2 += 'R';
				j++;
			}
			if (ch == 'L') {
				j--;
				if (j < N-1) outpath2 += 'L';
			}
			if (ch == 'D') {
				if (i < N-1) outpath2 += 'D';
				i++;
			}
			if (ch == 'U') {
				i--;
				if (i < N-1) outpath2 += 'U';
			}
		}

		/*
		if (1) {
			rep(i,0,N) {
				rep(j,0,N) {
					cerr << (query2(i, j) ? '.' : '#');
				}
				cerr << endl;
			}

			cerr << "! " << outpath2 << endl;
		}
		*/
		string s;
		for (char ch : outpath2) {
			if (s.empty()) {
				s.push_back(ch);
				continue;
			}
			if (ch == 'L' && s.back() == 'R') { s.pop_back(); continue; }
			if (ch == 'R' && s.back() == 'L') { s.pop_back(); continue; }
			if (ch == 'U' && s.back() == 'D') { s.pop_back(); continue; }
			if (ch == 'D' && s.back() == 'U') { s.pop_back(); continue; }
			s.push_back(ch);
		}
		cout << "! " << s << endl;
	}

}
