咋提杂题
The 1st Universal Cup. Stage 15: Hangzhou
A. Turn on the Light 2025-3-31
交互二分题
- 所有灯泡默认是暗的,要找出指定的灯泡y
? x
表示点亮第x个灯泡,同时返回abs(y左侧亮的灯泡数-y右侧亮的灯泡数)
! x
表示输出答案
由于绝对值的存在,二分check函数的判断很复杂。
- 若上一次询问返回的值等于这一次询问返回的值,则该灯泡就是答案,直接输出。
- 如果我们能使得左侧亮的灯泡数恒大于右侧亮的灯泡数,那么二分判断条件就明朗了
- 由于二分要进行logn次判断,那么我们先对前(1,logn)的灯泡进行询问。
- 然后对(logn,n)的区间进行二分,能保证在询问结束前左侧亮的灯泡数恒大于右侧亮的灯泡数。
同时看了dalao的题解,也可以将区间化为四等分判断解决。
The 1st Universal Cup. Stage 15: Hangzhou - 空気力学の詩 - 博客园
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| #include <iostream> #include <utility> using namespace std; typedef long long LL; const int N = 1e6 +10; int arr[N];
typedef pair<int, int> PA; typedef pair<PA, int> PA2; int n,m;
int flag = 0;
int ans(int x) { cout << "? "<< x << endl; cout.flush(); int tmp; cin >> tmp;
return tmp; } void print(int x) { cout << "! " << x << endl; cout.flush(); }
bool check(int x) { cout << "? "<< x << endl; cout.flush(); int tmp; cin >> tmp; if(tmp ==flag+1) { flag = tmp; return true; } else if (tmp == flag) { print(x); exit(0); } { flag = tmp; return false; } }
int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> n; int cnt = 0; int nn = n; while(nn) { cnt++; nn >>= 1; } for(int i = 1; i <= cnt; i++) { int tmp = ans(i); if(tmp == flag) { print(i); return 0; } else { flag = tmp; } } int left = cnt+1, right = n; int ans = -1; while (left <= right) { int mid = left + (right - left) / 2; if (!check(mid)) { ans = mid; right = mid - 1; } else { left = mid + 1; } } print(ans); }
|