#include <bits/stdc++.h>
using namespace std;
const int MAXN = 610;
int n;
int anc[MAXN], depth[MAXN];
bool mark[MAXN];
vector<int> adj[MAXN];
vector<int> partitions[2];
map<vector<int>, int> ans;
queue<int> q;
int qtdEdges(vector<int> a) {
  if (a.empty()) return 0;
  sort(a.begin(), a.end());
  if (ans[a] == 0) {
    cout << "? " << (int)a.size() << " ";
    for (int i = 0; i < (int)a.size(); i++) cout << a[i] << " ";
    cout << endl;
    cin >> ans[a];
    ans[a]++;
  }
  return ans[a] - 1;
}
int qtdCrossEdges(vector<int> A, vector<int> B) {
  vector<int> merge;
  for (int i = 0; i < (int)A.size(); i++) merge.push_back(A[i]);
  for (int i = 0; i < (int)B.size(); i++) merge.push_back(B[i]);
  return qtdEdges(merge) - qtdEdges(A) - qtdEdges(B);
}
void add(int node, int p) {
  q.push(node);
  mark[node] = true;
  anc[node] = p;
  depth[node] = depth[p] + 1;
  partitions[depth[node] % 2].push_back(node);
}
void findEdges(int root, vector<int> nodes, int qtd) {
  if (qtd == 0) return;
  if (nodes.empty()) return;
  if ((int)nodes.size() == 1) {
    add(nodes.front(), root);
    return;
  }
  int sz = (int)nodes.size();
  int m = sz / 2;
  vector<int> leftNodes, rightNodes;
  for (int i = 0; i < m; i++) leftNodes.push_back(nodes[i]);
  for (int i = m; i < (int)nodes.size(); i++) rightNodes.push_back(nodes[i]);
  findEdges(root, leftNodes, qtdCrossEdges(vector<int>(1, root), leftNodes));
  findEdges(root, rightNodes, qtdCrossEdges(vector<int>(1, root), rightNodes));
}
int findEndpoint(vector<int> L, vector<int> R) {
  if ((int)L.size() == 1) return L.front();
  int sz = (int)L.size();
  int m = sz / 2;
  vector<int> leftNodes, rightNodes;
  for (int i = 0; i < m; i++) leftNodes.push_back(L[i]);
  for (int i = m; i < (int)L.size(); i++) rightNodes.push_back(L[i]);
  if (qtdCrossEdges(leftNodes, R) != 0) return findEndpoint(leftNodes, R);
  return findEndpoint(rightNodes, R);
}
void findBadEdge(vector<int> nodes, int& A, int& B) {
  if (nodes.empty()) return;
  int sz = (int)nodes.size();
  int m = sz / 2;
  vector<int> leftNodes, rightNodes;
  for (int i = 0; i < m; i++) leftNodes.push_back(nodes[i]);
  for (int i = m; i < (int)nodes.size(); i++) rightNodes.push_back(nodes[i]);
  if (qtdEdges(leftNodes) != 0) {
    findBadEdge(leftNodes, A, B);
    return;
  }
  if (qtdEdges(rightNodes) != 0) {
    findBadEdge(rightNodes, A, B);
    return;
  }
  A = findEndpoint(leftNodes, rightNodes);
  B = findEndpoint(rightNodes, vector<int>(1, A));
}
int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    vector<int> aux(1, i);
    ans[aux] = 1;
  }
  add(1, 0);
  while (!q.empty()) {
    vector<int> remain;
    for (int i = 1; i <= n; i++)
      if (!mark[i]) remain.push_back(i);
    int cur = q.front();
    q.pop();
    findEdges(cur, remain, qtdCrossEdges(vector<int>(1, cur), remain));
  }
  int bad = -1;
  for (int i = 0; i < 2; i++)
    if (qtdEdges(partitions[i]) != 0) bad = i;
  if (bad == -1) {
    cout << "Y " << (int)partitions[0].size() << endl;
    for (int i = 0; i < (int)partitions[0].size(); i++)
      cout << partitions[0][i] << " ";
    cout << endl;
    return 0;
  }
  int A, B;
  findBadEdge(partitions[bad], A, B);
  if (depth[A] > depth[B]) swap(A, B);
  vector<int> pathA, pathB;
  while (depth[A] != depth[B]) pathB.push_back(B), B = anc[B];
  while (A != B) {
    pathA.push_back(A);
    A = anc[A];
    pathB.push_back(B);
    B = anc[B];
  }
  pathA.push_back(A);
  cout << "N " << (int)pathA.size() + (int)pathB.size() << endl;
  for (int i = 0; i < (int)pathA.size(); i++) cout << pathA[i] << " ";
  for (int i = (int)pathB.size() - 1; i >= 0; i--) cout << pathB[i] << " ";
  cout << endl;
}
