AtCoder Regular Contest 154 D. A + B > C ? (interactive thinking + sorting)

topic

interactive questions,

Each time a number n (1<=n<=2e3) is given, it means that there is a permutation p of length n at this time,

You can ask up to 25,000 times, and each time you ask,

Output three numbers that allow repetition i, j, k (1<=i, j, k<=n),

The interactive opportunity will tell you whether pi+pj>pk is established, if it is established, return Yes, otherwise return No

After all queries, you need to output permutation p

source of ideas

Ling tea group

answer

n<=2e3, q<=25000 times, it looks like O(nlogn),

The same is true in practice, the method is nlogn+n

1. First find the position of 1 through n times of inquiries, that is, traverse it once, maintain the minimum value,

Ask if 2*pi>pmn holds, where pmn is the subscript of the currently maintained minimum

If it is not established, it means that 2*pi<=pmn, and a new minimum value pmn has been found

When 1 appears, pmn will be replaced by the position of 1, and it will not change later, so one traversal is feasible

2. According to whether 1+pj>pk holds true, judge the relative position of j and k,

Since pj≠pk, if 1+pj>pk is established, it means pj>pk, otherwise pj<pk

As the sorting rule cmp function of the sort function,

The sort function may be selected because of the random axis, although the magnitude is O(nlogn),

But on the constant, the actual number of times will slightly exceed the limit

Therefore, the stable_sort function is used here, the internal merge sort is stable nlogn times

(It feels like a similar sort has been done before)

the code

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N=2e3+10;
int n,mn=1,rk[N],a[N];
string s;
bool ask(int i,int j,int k){
    cout<<"? "<<i<<" "<<j<<" "<<k<<endl;
    cin>>s;
    return s[0]=='Y';
}
int main(){
    cin>>n;
    for(int i=1;i<=n;++i){
        //2*pi<=mn,mn=pi
        rk[i]=i;
        if(!ask(i,i,mn)){
            mn=i;
        }
    }
    stable_sort(rk+1,rk+n+1,[&](int x,int y){
        return !ask(mn,x,y);
    });
    for(int i=1;i<=n;++i){
        a[rk[i]]=i;
    }
    cout<<"!";
    for(int i=1;i<=n;++i){
        cout<<" "<<a[i];
    }
    cout<<endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/Code92007/article/details/128761950