• CF1147E Rainbow Coins


    洛谷传送门 CF传送门

    题意

    (n) 个硬币,每个硬币有一种颜色,是R,G,B中的一种。可以选择两个硬币进行询问颜色是否一样,每次可以同时询问若干对硬币(一个硬币不能同时属于两对)。最多7次询问,将硬币分为颜色不同的三组。

    Solution

    这是个思维很棒的交互题。

    我们可以先询问两次:

    1.第一次询问 (2i-1,2i ightarrow 1 2|3 4|56 |cdots)

    2.第二次询问 (2i,2i+1 ightarrow 23|45|67|cdots)

    这样做可以得到两边相邻的颜色是否一样。

    如果一样,就将他们合并。设合并完用 (now) 表示,那么此时对于 (now_i)(now_{i-1},now_{i+1}) 和它的颜色都不一样。

    但是 (now_{i-1},now_{i+1}) 之间的关系我们还不知道,所以还要询问两次:

    1.第三次询问 (now_{i-2},now_{i})

    2.第四次询问 (now_i,now_{i+2})

    此时我们对于所有硬币之间的关系就都知道了,然后扫一遍求答案即可

    Code

    #include<bits/stdc++.h>
    #define PII pair<int,int>
    
    using namespace std;
    const int N=100010;
    int T,n,cnt,now[N],ans[N];
    char ch[N];
    vector<int>A,B,C;
    map<PII,bool>col;
    
    inline void ask(){
        if(!A.size()) return ;
        printf("Q %d ",(int)A.size());
        for(int i=0;i<A.size();i++) printf("%d %d ",A[i],B[i]);
        puts("");
        fflush(stdout);
        scanf("%s",ch+1);
        for(int i=0;i<A.size();i++) col[make_pair(A[i],B[i])]=(ch[i+1]=='1');
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            cnt=0;col.clear();
            memset(ans,0,sizeof(ans));
            scanf("%d",&n);
            A.clear();B.clear();
            for(int i=2;i<=n;i+=2){
                A.push_back(i-1);
                B.push_back(i);
            }
            ask();
            A.clear();B.clear();
            for(int i=3;i<=n;i+=2){
                A.push_back(i-1);
                B.push_back(i);
            }
            ask();
            now[++cnt]=1;
            for(int i=2;i<=n;i++)
                if(!col[make_pair(i-1,i)]) now[++cnt]=i;
            A.clear();B.clear();
            for(int i=3;i<=cnt;i+=4) A.push_back(now[i-2]),B.push_back(now[i]);
            for(int i=4;i<=cnt;i+=4) A.push_back(now[i-2]),B.push_back(now[i]);
            ask();
            A.clear();B.clear();
            for(int i=3;i<=cnt-2;i+=4) A.push_back(now[i]),B.push_back(now[i+2]);
            for(int i=4;i<=cnt-2;i+=4) A.push_back(now[i]),B.push_back(now[i+2]);
            ask();
            ans[now[1]]=1;
            if(cnt>1) ans[now[2]]=2;
            for(int i=3;i<=cnt;i++){
                if(col[make_pair(now[i-2],now[i])]) ans[now[i]]=ans[now[i-2]];
                else ans[now[i]]=6-ans[now[i-2]]-ans[now[i-1]];
            }
            A.clear();B.clear();C.clear();
            for(int i=1,t;i<=n;i++){
                if(ans[i]) t=ans[i];
                ans[i]=t;
                if(ans[i]==1) A.push_back(i);
                else if(ans[i]==2) B.push_back(i);
                else if(ans[i]==3) C.push_back(i);
            }
            printf("A %d %d %d
    ",(int)A.size(),(int)B.size(),(int)C.size());
            for(int i=0;i<A.size();i++) printf("%d ",A[i]);
            puts("");
            for(int i=0;i<B.size();i++) printf("%d ",B[i]);
            puts("");
            for(int i=0;i<C.size();i++) printf("%d ",C[i]);
            puts("");
            fflush(stdout);
        }
    }
    
  • 相关阅读:
    Java集合知识点小结
    集合类说明及区别
    微信翻译机器人实战
    细说:域名与SEO存在什么关系
    我为PHP摇旗呐喊!
    每个程序员都该知道的10大编码原则
    浏览器加载模式:window.onload和$(document).ready()
    修改Mysql编码集
    java实现LIS算法,出操队形问题
    [笔记]: 前向星 标签: 数据结构存储 2017-05-25 09:13 35人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/jasony/p/13872572.html
Copyright © 2020-2023  润新知