# MDCPP 外掛二分搜 + 模擬賽前總複習 --- ## 外掛二分搜 --- 我覺得我上次講的那題有點太難了 所以我換了一題 --- 直線上有 N 個要服務的點,每架設一座基地台可以涵蓋直徑 R 範圍以內的服務點。 輸入服務點的座標位置以及一個正整數 K,請問:在架設 K 座基地台以及每個基地台的直徑皆相同的條件下,基地台最小直徑 R 為多少 座標範圍不超過 1e9,1≤ K < N ≤ 5e4。 --- 看到了 ! 這又是外掛二分搜的模型拉 ~ ```給你一些條件,問你最少 / 最多要多少才能滿足條件``` --- 我們又可以嘗試用外掛二分搜解決這個問題 我們可以嘗試二分搜基地台直徑 R 我們就能夠進行確認是否能覆蓋的測試 --- 若能,就將二分範圍降至 左界 ~ mid-1 反之,就將二分範圍增至 mid+1 ~ 右界 --- 那我們要怎麼確認呢 ? --- 我們紀錄一個變數 $lp$ 代表目前能夠達到的基地台覆蓋範圍 並且遍歷位址陣列 若還能夠覆蓋的話,就不多設一個基地台 反之,就多設一個,修改 $lp$ --- ```cpp= #include <bits/stdc++.h> #define endl '\n' #define mid ((l+r)>>1) using namespace std; const int maxn = 2e5 + 5 ; const int mod = 1e9 + 7 ; const int INF = 1e9 + 9 ; int p[maxn],n,k; bool check(int x) { int lp=-1,cnt=0; for(int i=1;i<=n;i++) { if(p[i]>=lp) { cnt++; lp=p[i]+x/2; } } if(cnt>=k) return false; else return true; } signed main() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>p[i]; int l=1,r=1e5,ans; while(l<=r) { if(check(mid)) ans=mid,r=mid; else l=mid; } cout<<ans<<endl; } ``` --- ``` test case: 6 2 5 2 1 7 5 8 _*___*____ 00__0_00__ ``` --- 這個也有在證書題單裡面喔 ~ --- ## 來到我們的歡樂的模擬考前 ## 複習時間 ~ --- ## 第一堂課 --- 1. 萬用標頭檔 ```cpp= #include <bits/stdc++.h> ``` 2. #define (a) (b) ```cpp= #define int long long #define endl '\n' #define add(a,b) (a+b) #define pb push_back ``` 3. 時間複雜度 O() ```cpp= // O(n) for(int i=0;i<n;i++) cout<<i<<'\n'; // O(n^2) for(int i=0;i<n;i++) for(int j=0;j<n;j++) cout<<j<<'\n'; // O(logn) std::lower_bound(arr,arr+n,3) ``` 4. struct 結構體 ```cpp= struct strc { int a,b; char ch; int add() { return a+b; } } strc1,strc2[10]; strc1.add() int add(strc s1) { return s1.a+s1.b; } ``` 5. 自訂函數 ```cpp= int printnum(int x) { cout<<x<<endl; return x; } ``` 6. 排序 & 自訂排序 ```cpp= bool compare(int a,int b) { return a<b; } std::sort(arr,arr+n); std::sort(arr,arr+n,greater<int>()); std::sort(arr,arr+n,compare); ``` 7. 常見函式 ```cpp= std::swap(a,b); std::min(a,b); std::max(a,b); ``` --- ## 第二堂課 1. 簡單遞迴語法 ```cpp= int print(x) { if(x<=0) return 0; cout<<"First output of"<<x<<':'<<x<<endl; int t=print(x-1); cout<<"Second output of"<<x<<':'<<t<<endl; } ``` 2. 應用 ```cpp= //For instance : int gcd(int a,int b) { if(a==0) return b; else return gcd(b,a%b); } ``` --- ## 第三堂課 1. 堆疊 stack ```cpp= stack<int>stk; stk.push(1); // an operation used to push a number on the top of the stack stk.pop(); // an operation used to pop the number on the top of the stack stk.size(); // an integer, the size of the stack stk.top(); // the top of the stack stk.empty(); // a boolean number, checking whether the stack is empty or not ``` 2. 佇列 queue ```cpp= queue<int>q; q.push(1); // an operation used to push a number on the back of the queue q.pop(); // an operation used to pop a number on the front of the queue q.size(); // an integer, the size of the queue q.front(); // the front of the queue q.empty(); // a boolean number, checking whether the vector is empty or not ``` 3. 動態陣列 (向量?) vector ```cpp= vector<int>v; v.push_back(1); v.pop_back(); v.empty(); v.size(); v.front(); v.back(); v.clear(); v.push_front(); // Please do not use the function because it's time complexity is O(n) v.pop_front(); // Please do not use the function because it's time complexity is O(n) v.erase(v.begin()); // Please do not use the function because it's time complexity is O(n) v.begin(); v.end(); v.resize(); sort(v.begin(),v.end()); . . . // Anyway you can just google it ``` 4. 雙向佇列 deque ```cpp= deque<int>dq; dq.push_back(); dq.pop_back(); dq.push_front(); dq.pop_front(); dq.size(); dq.empty(); dq[2]; // to be honest, I do not know the exact time complexity of this. Anyway do not use this function. ``` --- [資料結構練習題](https://zerojudge.tw/ShowProblem?problemid=a565) --- ## 第四堂課 --- 1. 集合 set ```cpp= set<int>st; // or multiset<int>st st.begin(); // *iterator st.rbegin(); // *reverse_iterator st.erase(st.find(3)); st.insert(5); st.clear(); st.empty(); st.size(); ``` 2. ( 我找不到中文 ) map ```cpp= O(logn) map<long long,int>mp; mp.begin(); mp.rbegin(); mp.erase(4); mp[5]=6; mp.clear(); ``` 3. unordered_map ```cpp= unordered_map<int,int>mp; O(1) ``` 4. 優先佇列 prioirty_queue ```cpp= //O(logn) priority_queue<int>pq; pq.push(1); pq.pop(); pq.top(); pq.empty(); pq.size(); ``` --- [動態資料結構練習題](http://mdcpp.mingdao.edu.tw/problem/B033) --- ## 第五堂課 --- 1. 二分搜 simple_binary search ```cpp= int simple_binary_search(int* arr[],int n,int k) { int l=1,r=n,ans=-1; while(l<=r) { int mid=(l+r)/2; if(arr[mid]>k) { r=mid-1; } else { ans=mid; l=mid+1; } } return ans; } ``` 2. 跳躍二分搜 jump_binary_search ```cpp= int jump_binary_search(int* arr[],int n,int k) { for(int i=n;i>0;i=i/2) { int pos=0; if(arr[pos+i]<=k) { ans=pos+i; pos+=i; } else if(arr[pos]<=k) { ans=pos; } } return ans; } ``` 3. STL 二分搜 ```cpp= int STL_binary_search(int* arr[],int n,int k) { auto it=upper_bound(arr+1,arr+1+n,k); return *--it; } ``` 4. 動態二分搜 dynamic binary search ```cpp= int dynamic_binary_search(set<int>* st,int k) { auto it=st.upper_bound(k); return *--it; } ``` 5. 外掛二分搜 ```cpp= // 請往上找 ``` --- [二分搜練習題](https://zerojudge.tw/ShowProblem?problemid=c179) --- ## 第六堂課 --- 1. 外掛二分搜 https://reurl.cc/ARDAke 2. 總複習 https://reurl.cc/35mxa8