D. Sum Graph
题意:
(交互题)
有一个未知的序列 ,这个序列是 的一种排列,例当 时,一种排列是 。
给定两种操作:
1、输出 "+ x" 表示将所有满足 的点连一条边。
2、输出 "? x y" 表示询问数字 x 和 y 之间的最短路径长度。
要求操作总次数小于等于2n。
题解:
首先输出 "+ n+1" 和 "+ n+2" ,此后变成了一个全联通图。
此后只需求出这个联通图的左右端点,即可求出具体的序列,即找树的直径。
具体代码如下:
#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#define int long long
#define pi acos(-1)
#define quick_cin() cin.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
#define pb push_back
#define all(x) x.begin(), x.end()
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int N = 2010, M = 50, P = 131;
const int mod = 1e9 + 7, Mod = 998244353;
const int INF = 1e18, __int128_INF = 1e38;
const int base = 1e9 + 7;
const double esp = 1e-6;
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
int n, T, k, m;
int res = 0;
PII g[N];
int ans[N];
int res1[N], res2[N];
bool cmp(PII a, PII b)
{
return a.first < b.first;
}
void solve()
{
cin >> n;
cout << "+ " << n + 1 << endl;
cout << "+ " << n + 2 << endl;
int d1 = 0;
int pos;
int root = 1;
for (int i = 2; i <= n; i ++ )
{
int d;
cout << "? " << root << " " << i << endl;
cin >> d;
if (d > d1)
{
d1 = d;
pos = i;
}
}
int idx = 1;
g[idx] = {0, pos};
for (int i = 1; i <= n; i ++ )
{
if (i == pos) continue;
int d;
cout << "? " << pos << " " << i << endl;
cin >> d;
g[ ++ idx ] = {d, i};
}
idx = 1;
int l = 1, r = n;
while (l <= r)
{
ans[idx ++ ] = l ++ ;
if (l > r) break;
ans[idx ++ ] = r -- ;
}
sort(g + 1, g + 1 + n, cmp);
for (int i = 1; i <= n; i ++ )
{
int p = g[i].second;
res1[p] = ans[i];
res2[p] = ans[n - i + 1];
}
cout << "!";
for (int i = 1; i <= n; i ++ ) cout << " " << res1[i];
for (int i = 1; i <= n; i ++ ) cout << " " << res2[i];
cout << endl;
}
signed main()
{
quick_cin();
cin >> T;
// getchar();
// T = 1;
while (T -- )
{
solve();
}
return 0;
}