CF1697D. Guess The String (交互题)
https://codeforces.com/contest/1697/problem/D
题意:
有一个长度为n的有小写字母组成的字符串,
Ⅰ操作:查询i位置上的字母 (不超过26次)
Ⅱ操作:查询 l到r字母种类数 (不超过6000次)
思路:
- Ⅰ操作只能那个进行26次,可以想到从1到n查询前缀,si的种类数和si-1不同就说明i位置上是之前没有出现过的字母。
- 相同的话,考虑用Ⅱ操作判出i是哪个字母:保留每个字母最后一次出现的位置,根据种类数二分出和i相同的字母,Ⅱ操作最多用1000log26次
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define PII pair<int, char>
//#define int long long
const int N = 2e5 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double PI = acos(-1.0);
void solve() {
int n; cin >> n;
vector<PII> ve; string ans;
cout << "? 1 " << 1 << endl;
char x; cin >> x;
ve.push_back({1, x}); ans += x;
for ( int i = 2; i <= n; ++ i ) {
cout << "? 2 " << 1 << " " << i << endl;
int ty; cin >> ty;
if( ty > ve.size() ) {
cout << "? 1 " << i << endl;
char x; cin >> x;
ve.push_back({i, x}); ans += x;
} else {
sort(ve.begin(), ve.end()); int sz = ve.size();
int l = 0, r = ve.size() - 1;
while( l < r ) {
int mid = l + r + 1 >> 1;
cout << "? 2 " << ve[mid].first << " " << i << endl;
int ty; cin >> ty;
if( ty == sz - (mid + 1) + 1 ) l = mid;
else r= mid - 1;
}
ve[l].first = i; ans += ve[l].second;
}
}
cout<<"! "<<ans<<endl;
}
int main () {
IOS
int t = 1;// cin >> t;
while ( t -- ) solve();
return 0;
}
本文作者:qingyanng
本文链接:https://www.cnblogs.com/muscletear/p/16398079.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步