Codeforces Round #669 (Div. 2) C. Chocolate Bunny

翻译:

这是一个互动的问题。

我们向您隐藏了一个长度为𝑛的排列𝑝,由从1到𝑛的元素组成。你想猜一下。为此,你可以给我们2个不同的索引𝑖和𝑗,我们将回复𝑝𝑖mod𝑝𝑗(𝑝𝑖除以𝑝𝑗的余数)。

我们有足够的耐心回答最多2⋅𝑛的问题,所以你应该符合这个限制。你能做到吗?

提醒一下,长度为𝑛的排列是一个由𝑛个从1到𝑛的不同整数以任意顺序组成的数组。例如,[2,3,1,5,4]是一个排列,但[1,2,2]不是一个排列(2在数组中出现两次),[1,3,4]也不是一个排列(𝑛=3,但数组中有4)。

输入
输入的唯一一行包含一个整数𝑛(1≤𝑛≤104)-排列的长度。

交互
互动从阅读𝑛开始。

那么你最多可以进行2⋅𝑛的查询,方法如下:

”?X y”(1≤𝑥,𝑦≤𝑛,𝑥≠𝑦)。
在每一个之后,您应该读取一个整数𝑘,它等于𝑝𝑥mod𝑝𝑦。

当你猜出排列后,打印一行“!”(不带引号),后面跟着数组𝑝和quit。

打印查询后,不要忘记输出行尾并刷新输出。否则,您将得到闲置限制超过。要做到这一点,请使用:

c++中的fflush(stdout)或count .flush();
Java中的System.out.flush();
Pascal中的flush(输出);
Python中的stdout.flush();
有关其他语言,请参阅文档。
收到“-1”后立即退出,你将看到错误答案判决。否则,您可能会得到一个任意的裁决,因为您的解决方案将继续从一个封闭的流中读取。

修改格式

在第一行输出𝑛(1≤𝑛≤104)。在第二行中,打印𝑛整数的排列𝑝1,𝑝2,…,𝑝𝑛。

例子
inputCopy
3.

1

2

1

0
outputCopy
? 1 2

? 3 - 2

? 1 3

? 2 1

! 1 3 2

思路:2*n次查询,刚开始没有思路,然后写了下,发现,如果a>b,那么a%b一定是小于b的,如果b>a,a%b一定是a,那么a一定比可以取余的大,因为取余过后肯定是比a,b小的。所以我们每次对相同的两个位置,轮流查询,答案大的那个就是其中小的那个,因为小的被比其大的数取余肯定是本身,所以我们可以两次得到一个答案,之后如果剩下一个了,就可以break了,打个标记就可以确定最后一个在哪里了。

代码:

/*Looking! The blitz loop this planet to search way
 
 Only my RAILGUN can shoot it 今すぐ
 
 身体中を  光の速さで
 
 駆け巡った確かな予感
 
 掴め! 望むものなら残さず
 
 輝ける自分らしさで
 
 信じてるよ  あの日の誓いを
 
 この瞳に光る涙それさえも  強さになるから
 
 */
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
using namespace::std;
typedef long long  ll;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}
int n;
int an[10005];
int ff,ns;
int a,b;
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    if (n==1) {
        printf("! 1\n");return 0;
    }
    memset(an, -1, sizeof an);
    queue<int>q;
    for (int i=1; i<=n; i++) {
        q.push(i);
    }
    while (1) {
        if (q.size()==1) {
            break;
        }
        ff=q.front();
        q.pop();
        ns=q.front();
        q.pop();
        cout<<"? "<<ff<<" "<<ns<<endl;
        cin>>a;
        cout<<"? "<<ns<<" "<<ff<<endl;
        cin>>b;
        if (a>b) {
            an[ff]=a;
            q.push(ns);
        }
        else{
            an[ns]=b;
            q.push(ff);
        }
    }cout<<"! ";
    for (int i =1; i<=n; i++) {
        if (an[i]==-1) {
            cout<<n<<" ";
//            printf("%d ",q.front());
        }
        else{
            cout<<an[i]<<" ";
//            printf("%d ",an[i]);
        }
    }
    
    
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值