zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    rabbitMQ 的简单模式
    redis 的发布订阅
    redis 的管道操作
    redis 的其他常用操作
    redis 的链表操作
    redis 的哈希操作
    redis 的字符串操作
    redis 的数据类型
    Redis的基本操作
    day27 的笔记和day 25 的保持一致
  • 原文地址:https://www.cnblogs.com/MXang/p/11779110.html
Copyright © 2011-2022 走看看