【学习笔记】CF1292E Rin and The Unknown Flower

题目太难,我想摆了。

这题咋做嘛,人脑搜索呗。

难就难在,如果第一步搜索就走错了,后面的步骤难度就大了。

如果询问单个字符,虽然这样字符集大小变成了 2 2 2,但是这一步花销太大了,以至于难以为继。

于是我们可以通过询问 C H , C O , H C , H O CH,CO,HC,HO CH,CO,HC,HO来代替,这一步花销是 1 1 1

如果有位置没有被确定,那么要么是 O ? O? O?,要么是两个相同字符。

我们分两种情况讨论。

1.1 1.1 1.1 如果所有位置都是 ? ? ?, 那么打表观察一下,我们发现此时字符集大小为 2 2 2,并且 O O O一定在字符集内。我们可以先询问 O O O OOO OOO,如果成功了就能确定一段前缀,再询问一次整个串长度即可。否则,我们可以再询问 H H H , C C C HHH,CCC HHH,CCC,能够确定出后缀长度。当 n = 4 n=4 n=4时我们还要额外询问一次整个串长度,有最大花费 1 + 1 3 + 1 16 < 1.4 1+\frac{1}{3}+\frac{1}{16}<1.4 1+31+161<1.4

1.2 1.2 1.2 如果有位置被确定出来了,考虑找到最右边的位置,比如是 ? ? . . . C H . . . ??...CH... ??...CH...,往后推非常容易,肯定都是 H H H,往前推的话,考虑有些不合法的情况可以被剪掉,因此只需要询问一次就能确定一位的答案,考虑最极端的情况, 1 + ∑ i = 3 50 1 i 2 < 1.4 1+\sum_{i=3}^{50}\frac{1}{i^2}<1.4 1+i=350i21<1.4 ,然后就做完了。如果是 ? ? . . . C O . . . ??...CO... ??...CO...呢?那么还是先往前面推,往后推的时候,就只能暴力试了,不过可以考虑先试 O O O,如果这一位还是 ? ? ?就只能是 C , H C,H C,H,那么后面就都可以确定了,因此可以通过。

如何做这种题做得更快一些?升级大脑呗。

#include<bits/stdc++.h> #define ll long long #define pb push_back #define db double using namespace std; int T,n; string res; string s[4]={"CH","CO","HC","HO"}; char ch[3]={'C','H','O'}; void ask(string s){ cout<<"?"<<" "<<s<<endl; int k;cin>>k; for(int i=1;i<=k;i++){ int x;cin>>x; for(int j=0;j<s.size();j++)res[x+j]=s[j]; } } bool check(char x,char y){ if(x=='C'&&y=='H'||x=='C'&&y=='O'||x=='H'&&y=='C'||x=='H'&&y=='O')return 1; return 0; } string solve(){ for(int i=1;i<=n;i++)res[i]='?'; for(int i=0;i<4;i++)ask(s[i]); int ok=0; for(int i=1;i<=n;i++)if(res[i]!='?')ok=1; if(!ok){ ask("OOO"); int ok2=0; if(res[1]!='?'){ string tmp,tmp2; for(int i=1;i<=n;i++){ if(res[i]!='?')tmp+=res[i]; else tmp+='C'; } ask(tmp); if(res[n]!='?'){ return tmp; } for(int i=1;i<=n;i++){ if(res[i]!='?')tmp2+=res[i]; else tmp2+='H'; } return tmp2; } ask("HHH"),ask("CCC"); if(res[n]!='?'){ string tmp; for(int i=1;i<=n;i++){ if(res[i]!='?')tmp+=res[i]; else tmp+='O'; } return tmp; } ask("OOCC"); if(res[1]!='?'){ return "OOCC"; } return "OOHH"; } int now=0; for(int i=n;i>=1;i--){ if(res[i]!='?'){ now=i; break; } } for(int i=now-2;i>=1;i--){ if(res[i]=='?'){ for(int j=0;j<3;j++){ if(res[i]=='?'&&!check(ch[j],res[i+1])){ string tmp;tmp+=ch[j]; for(int k=i+1;k<=now;k++)tmp+=res[k]; ask(tmp); if(res[i]=='?'){ for(int k=0;k<3;k++){ if(k!=j&&!check(ch[k],res[i+1])){ res[i]=ch[k]; } } } } } } } while(now<n&&res[now]=='O'){ string tmp; for(int i=1;i<=now;i++)tmp+=res[i]; ask(tmp+'O'); if(res[now+1]=='?'){ ask(tmp+'C'); } if(res[now+1]=='?'){ res[now+1]='H'; } now++; } if(now<n){ for(int i=now+1;i<=n;i++)res[i]=res[now]; } string tmp; for(int i=1;i<=n;i++){ tmp+=res[i]; } return tmp; } int main(){ ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>T; while(T--){ cin>>n;res.clear(),res.resize(n+5); string o=solve(); cout<<"!"<<" "<<o<<endl; int ok;cin>>ok; assert(ok); } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530000.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
历史上的今天:
2022-03-31 【题解】「SCOI2011」棘手的操作
点击右上角即可分享
微信分享提示