gym 102392 C

Posted mxang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gym 102392 C相关的知识,希望对你有一定的参考价值。

题意
给你250个不同的数
每次操作可以查询单个位置的数,
或者查询k个位置的数两两的差的绝对值(返回乱序的k*(k-1)/2个数)
最多三十次操作还原这个数列

这简直太神妙了!
首先确定某个极值的下标,这个二分就行了。
然后我们看一下这是极大还是极小。两次询问即可。

神妙的东西来了!
我们怎么知道每个位置与当前极值到底差多少呢???
我们发现,n个数字都是不相同的!也就是说每个『差』只会出现一次。
那么我们枚举二进制位,如果这个『差』出现了,我们就给这个差的下标加上枚举的二进制下标
这样就能得到每个『差』对应的唯一位置。
还原即可

这个题完全没想到n个数字不同的用处。。。

我完蛋了啊

#include <bits/stdc++.h>
using namespace std;
int ask(int x){
    cout<<"2 "<<x;
    for(int i=1;i<=x;i++)cout<<' '<<i;
    cout<<endl;
    fflush(stdout);
    int p=0;
    for(int i=1,s;i<=x*(x-1)/2;i++){
        cin>>s;
        p=max(p,s);
    }
    return p;
}
vector<int> ask(int id,vector<int> &v,int sz){
    map<int, int> mp;
    if(sz>=2) {
        cout << "2 " << sz;
        for (auto x:v)cout << ' ' << x;
        cout << endl;
        fflush(stdout);
        for (int i = 1, s; i <= sz * (sz - 1) / 2; i++) {
            cin >> s;
            mp[s]--;
        }
    }
    sz++;v.push_back(id);
    cout<<"2 "<<sz;
    for (auto x:v)cout << ' ' << x;
    cout << endl;
    fflush(stdout);
    for(int i=1,s;i<=sz*(sz-1)/2;i++){
        cin>>s;
        mp[s]++;
    }
    vector<int> res;
    for(auto p:mp){
        if(p.second>0)
            res.push_back(p.first);
    }
    return res;
}
int n;
int ans[256];
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    if(n<=2){
        for(int i=1,x;i<=n;i++){
            cout<<"1 "<<i<<endl;
            fflush(stdout);
            cin>>x;
            ans[i]=x;
        }
        cout<<"3";
        for(int i=1;i<=n;i++)cout<<' '<<ans[i];
        cout<<endl;
        fflush(stdout);
        return 0;
    }
    int mxd = ask(n);
    int l=1,r=n;
    while (l<=r){
        int mid = l+r>>1;
        if(ask(mid)==mxd){
            r=mid-1;
        }else{
            l=mid+1;
        }
    }
    int mxid = l;//某个极值
    map<int,int> mp;
    for(int i=0;i<8;i++){
        vector<int> pos;
        for(int j=1;j<=n;j++)if(j&(1<<i)&&j!=mxid)pos.push_back(j);
        if(pos.empty())continue;
        vector<int> res = ask(mxid,pos,pos.size());
        for(auto x:res){
            mp[x]+=(1<<i);
        }
    }
    for(auto x:mp){
        ans[x.second]=x.first;
    }
    int oth=1;
    if(mxid==1)oth=2;
    auto que = [](int ind)->int{cout<<"1 "<<ind<<endl;fflush(stdout);cin>>ind;return ind;};
    int v1 = que(mxid),v2 = que(oth);
    if(v1>v2){
        cout<<"3";
        for(int i=1;i<=n;i++){
            cout<<' '<<v1-ans[i];
        }
        cout<<endl;
    }else{
        cout<<"3";
        for(int i=1;i<=n;i++){
            cout<<' '<<v1+ans[i];
        }
        cout<<endl;
    }
    fflush(stdout);
}

以上是关于gym 102392 C的主要内容,如果未能解决你的问题,请参考以下文章

codeforeces GYM 101142 C

Gym 240668 - A/B/C/D/E - (Done)

gym/102253C Colorful Tree 树上计数

莫比乌斯反演模板--Gym 101982B

Gym - 101982B Coprime Integers (莫比乌斯反演)

2016 USP-ICMC-Codeforces-Gym101063C-Sleep Buddies Gym101063F-Bandejao Gym101063J-The Keys