「USACO06NOV」玉米田 Corn Fields
阿新 • • 發佈:2020-08-09
基礎知識:
tips: 版本1用來求符合條件的值中下標最小的那個,版本2求符合條件中的下標最大的那個。
1. 最佳牛圍欄
題目連結:https://www.acwing.com/problem/content/104/(演算法競賽進階指南)
思路:1. 二分的方法來列舉所有可能的平均值
2. 檢驗當前的平均值是否符合條件, 如果符合條件就調大平均值,如果不符合條件就減小平均值
3. 檢驗方法:求當前陣列的字首和並將每一項都減去平均值。記錄所有大於等於m長度的區間的值,
如果有區間的值大於1,說明對於該區間,當前平均值偏小,即符合條件。
程式碼:
#include <iostream> #include <algorithm> using namespace std; const int N = 100010; int n, m; int cows[N]; double sum[N]; bool check(double avg) { for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + cows[i] - avg; double minv = 0; for(int i = 0, j = m; j <= n; j++, i++) {//儲存所有區間的最小值,因為j是從m開始列舉, //因此字首區間sum[j] - sum[i]的長度一定大於m minv = min(minv, sum[i]); if(sum[j] >= minv) return true; } return false; } int main() { cin >> n >> m; for(int i = 1; i <= n; i++) cin >> cows[i]; double left = 0, right = 2000; while(right - left > 1e-5) { double mid = (left + right) / 2; if(check(mid)) left = mid; else right = mid; } printf("%d\n", int(right * 1000)); return 0; }
2.特殊排序
題目連結:https://www.acwing.com/problem/content/115/(演算法競賽進階指南)
思路:
方法1:每次取出一個數字,通過二分的方法找到這個數字在當前陣列中的位置,將當前元素新增到vector最後,通過插入排序將當前元素放到正確的位置
程式碼1:
class Solution { public: vector<int> specialSort(int N) { vector<int> res; res.push_back(1); for(int i = 2; i <= N; i++) { int left = 0; int right = res.size() - 1; while(left < right) { int mid = left + right + 1 >> 1; if(compare(res[mid], i)) left = mid; else right = mid - 1; } res.push_back(i); for(int j = res.size() - 2; j > right; j--) { swap(res[j], res[j + 1]); } //排除邊界條件,如果所有的數字都大於當前的數字,需要特殊判斷 if(compare(i, res[right])) swap(res[right], res[right + 1]); } return res; } };
方法2:歸併排序
程式碼2:
class Solution { public: vector<int> merge(int l,int r,int N)//merge函式返回l到r區間已經排好序的vector容器 { if (l == r)//遞迴出口,如果只有一個元素,直接把這個元素返回即可 { vector<int>temp; temp.push_back(l); return temp; } int mid = (l + r) / 2; vector<int>a=merge(l,mid,N);//遞迴求解 vector<int>b=merge(mid+1,r,N); vector<int>res;//res是一會要返回的容器 int t1=0,t2=0;//t1和t2分別指向a和b容器中的元素 int flag=0; while(t1<a.size()&&t2<b.size()) { if(compare(a[t1],b[t2]))//如果a中元素小,就把a中元素壓入res中 { res.push_back(a[t1++]); } else { res.push_back(b[t2++]); } if(t1>=a.size())//如果t1已經指向了a容器末尾,flag=1表示a已經遍歷完全 { flag=1;break; } if(t2>=b.size())//同理 { flag=2;break; } } if(flag==1)//把b中剩餘元素壓入res中 { for(int i=t2;i<b.size();i++) { res.push_back(b[i]); } } else//同理 { for(int i=t1;i<a.size();i++) { res.push_back(a[i]); } } return res; } vector<int> specialSort(int N) { vector<int>ans=merge(1,N,N); return ans; } };