# D. Guess The String link : https://codeforces.com/problemset/problem/1697/D tóm tắt đề : cho xâu độ dài cố định n, có 2 loại truy vấn: 1 : hỏi 1 kí tự tại i (tối đa 26 lần hỏi) 2 : hỏi có bao nhiêu kí tự khác nhau trong [l...r] (tối đa 6000 lần hỏi) Mục tiêu : đoán xâu ban đầu + suy nghĩ 1 : thao tác 1 rất có thể là để đoán vừa đủ lượng kí tự, thao tác 2 có vẻ là dùng thoải mái. + suy nghĩ 2 : đã có cách để dùng chặt nhị phân để đoán được, tuy nhiên số thao tác loại 2 cần hơn 8000 lần hỏi. + suy nghĩ 3 : giảm số lượng vị trí cần quan tâm, đưa về mỗi vị trí hỏi tối đa log2(26) lần hỏi. code AC : :::spoiler ```cpp #include<bits/stdc++.h> #define pii pair<int, int> #define REP(i, a, b) for (int i = (a); i <= (b); ++i) #define X first #define Y second using namespace std; const int mxn = 5e5 + 5; char s[mxn]; char fi(int x) { set<char> tmp; vector<int> tap; for (int i = x - 1; i >= 1; --i) if (tmp.find(s[i]) == tmp.end()) { tmp.insert(s[i]); tap.push_back(i); } reverse(tap.begin(), tap.end()); int l = 0, r = tap.size(); while(l < r) { int mid = (l + r)/2; cout << "? 2 " << tap[mid] << ' ' << x << endl; int y; cin >> y; if (y > tap.size() - mid) r = mid; else l = mid + 1; } return s[tap[l - 1]]; } int main() { int n; cin >> n; cout << "? 1 1" << endl; cin >> s[1]; int tong = 1; REP(i, 2, n) { cout << "? 2 1 " << i << endl; int x; cin >> x; if (x > tong) { cout << "? 1 " << i << endl; cin >> s[i]; ++tong; } else s[i] = fi(i); } cout << "! "; REP(i, 1, n) cout << s[i]; } ```