#include <iostream>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstdlib>

#define ll long long
#define ld long double
#define mp make_pair
#define sz(x) (int) x.size()

using namespace std;

#define TASKNAME ""

const int N = 3005;

int n;
vector<int> g[N];
int val[N];

int mem[N][N];

int query(int i, int j) {
	if (i >= j) return i == j ? 1 : 0;
	if (mem[i][j] != 0) return mem[i][j];
	cout << "? " << i + 1 << " " << j + 1 << endl;
	int ans;
	cin >> ans;
	mem[i][j] = ans;
	return ans;
}

int k;

void dfs(int v) {
	val[v] = k;
	for (int u : g[v]) {
		if (val[u] == -1) dfs(u);
	}
}

int nxt[N];

int main() {
	/*ios::sync_with_stdio(false);
	cout.tie(0);
	cin.tie(0);*/

#ifdef _DEBUG
	//freopen("input.txt", "r", stdin);
#else
	/*if (TASKNAME != "") {
		freopen(TASKNAME ".in", "r", stdin);
		freopen(TASKNAME ".out", "w", stdout);
	}*/
#endif

	cin >> n;

	for (int i = 0; i < n; i++) {
		int j = i;
		while (j + 1 < n && query(i, j + 1) == (j + 1) - i + 1) {
			j++;
		}

		for (int k = i; k <= j; k++) {
			nxt[k] = j;
		}

		i = j;
	}

	int diff = query(0, n - 1);
	int eq = n - diff;
	int cur = 0;

	for (int i = 0; i < n - 1 && cur < eq; i++) {
		int left = nxt[i];
		int right = n;

		if (query(i, n - 1) + 1 == query(i + 1, n - 1)) {
			continue;
		}

		while (right - left > 1) {
			int m = (left + right) / 2;
			if (query(i, m) == query(i + 1, m) + 1) {
				left = m;
			}
			else {
				right = m;
			}
		}

		if (right != n) {
			g[i].push_back(right);
			g[right].push_back(i);
			cur++;
		}
	}

	fill(val, val + n, -1);

	k = 0;
	for (int i = 0; i < n; i++) {
		if (val[i] == -1) {
			dfs(i);
			k++;
		}
	}

	cout << "Ready!" << endl;
	cout << k << endl;
	for (int i = 0; i < n; i++) {
		cout << val[i] + 1 << " ";
	}
	cout << endl;

#ifdef _DEBUG
	while (1);
#endif

	return 0;
}