题目大意:
给定一个长度为n的序列arr,里面的数字是1~n(顺序未知),现在允许你最多询问2n次,每次询问(输出)两个下标i,j,系统将告知(输入)你结果x=arr[i]%arr[j],请你确认序列arr
思路:
显然,如果a < b,那么有a % b = a,因此我们可以充分利用这一点,每次询问一组 i,j 和 j ,i ——系统会反回 x = arr[i] % arr[j] 和 y = arr[j] % arr[i],那么假如x > y,则可以确定arr[i] = x,否则可以确定 arr[j] = y。
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n, m, arr[N];
bool st[N]; //用于存储确定过的数字
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
cin>>n;
int idx = 1,a,b;
for(int i=2 ;i<=n ;i++)
{
//每次询问两组
cout<<"? "<<idx<<" "<<i<<endl;
cout.flush();
cin>>a;
cout<<"? "<<i<<" "<<idx<<endl;
cout.flush();
cin>>b;
//判断a,b大小,以确定arr[idx]或arr[i]
if(a>b)
{
arr[idx] = a, st[a] = true;
idx = i; //i未被确定则下次继续使用
}
else //idx未被确定直接继续使用
arr[i] = b, st[b] = true;
}
cout<<"! ";
for(int i=1 ;i<=n;i++)
if(arr[i]!=0) cout<<arr[i]<<" ";
else
{ //输出最后没有被确定的数字
for(int i=1;i<=n;i++)
if(!st[i])
cout<<i<<" ";
}
}