Codeforces Round 865 (Div. 2)-D. Sum Graph

该文章描述了一个关于序列排列的问题,其中涉及对未知序列的特定排列进行操作。主要操作包括在满足条件的点间建立边和查询两点间的最短路径。通过输出+n+1和+n+2将图变为全联通,然后找到树的直径以确定序列。解决方案是构建并查找联通图的最远两端点,从而得到原始序列。
摘要由CSDN通过智能技术生成

D. Sum Graph

题意:

(交互题)

有一个未知的序列 p_{1},p_{2}...p_{n} ,这个序列是 1-n 的一种排列,例当 n=3 时,一种排列是 1,3,2 。

给定两种操作:

1、输出 "+ x" 表示将所有满足 p_{i}+p_{j}=x(1\leqslant i,j\leqslant n) 的点连一条边。

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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值