zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    
  • 相关阅读:
    JVM工作原理--垃圾收集
    并发编程之单例模式
    设计模式之动态代理
    UML类图基础
    CAP理论的理解
    Dubbo RPC调用参数校验---错误message自动返回
    ELK日志分析系统搭建
    Kafka原理及应用(一)
    HTTPS的原理
    Maven 生命周期的概念(指令默认顺序执行)
  • 原文地址:https://www.cnblogs.com/jasony/p/13872572.html
Copyright © 2011-2022 走看看