知識點
如果一個區間,可以根據某種屬性,把區間分爲兩段,且一段滿足這個屬性,而另一段不滿足,我們就可以使用二分。
二分模板
while(l<r)
{
int mid=l+r>>1;
if(a[mid]>=x) r=mid;
else l=mid+1;
}
while(l<r)
{
int mid=l+r+1>>1;
if(a[mid]<=x) l=mid;
else r=mid-1;
}
最佳牛圍欄
農夫約翰的農場由 N 塊田地組成,每塊地裏都有一定數量的牛,其數量不會少於1頭,也不會超過2000頭。
約翰希望用圍欄將一部分連續的田地圍起來,並使得圍起來的區域內每塊地包含的牛的數量的平均值達到最大。
圍起區域內至少需要包含 F 塊地,其中 F 會在輸入中給出。
在給定條件下,計算圍起區域內每塊地包含的牛的數量的平均值可能的最大值是多少。
輸入格式
第一行輸入整數 N 和 F ,數據間用空格隔開。
接下來 N 行,每行輸出一個整數,第i+1行輸出的整數代表,第i片區域內包含的牛的數目。
輸出格式
輸出一個整數,表示圍起區域內每塊地包含的牛的數量的平均值可能的最大值乘以1000得到的數值。
數據範圍
1≤N≤100000
1≤F≤N
輸入樣例:
10 6
6
4
2
10
3
8
5
9
4
1
輸出樣例:
6500
這題的思路就是,我們二分所有可能的平均值,數據範圍完全在我們能接受的範圍內(n(logn)),然後我們Calc函數就是判斷當前平均值是否可行,如果可行,那麼向上繼續搜索,如果不可行向下搜索。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100010;
const double eps=1e-8;
int n,m,f[N];
double sum[N];
int MAX;
bool calc(double x)
{
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+f[i]-x;
double MIN=0;
for(int i=0,j=m;j<=n;j++,i++)
{
MIN=min(MIN,sum[i]);
if(sum[j]-MIN>=0)
return false;
}
return true;
}
int main(){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&f[i]),MAX=max(MAX,f[i]);
double l=0,r=MAX;
while(r-l>eps)
{
double mid=(l+r)/2;
if(calc(mid)) r=mid;
else l=mid;
}
printf("%d",int(r*1000));
return 0;
}
特殊排序
有N個元素,編號1.2…N,每一對元素之間的大小關係是確定的,關係不具有傳遞性。
也就是說,元素的大小關係是N個點與N*(N-1)/2條有向邊構成的任意有向圖。
然而,這是一道交互式試題,這些關係不能一次性得知,你必須通過不超過10000次提問來獲取信息,每次提問只能瞭解某兩個元素之間的關係。
現在請你把這N個元素排成一行,使得每個元素都小於右邊與它相鄰的元素。
你可以通過我們預設的bool函數compare來獲得兩個元素之間的大小關係。
例如,編號爲a和b的兩個元素,如果元素a小於元素b,則compare(a,b)返回true,否則返回false。
將N個元素排好序後,把他們的編號以數組的形式輸出,如果答案不唯一,則輸出任意一個均可。
數據範圍
1≤N≤1000
輸入樣例
[[0, 1, 0], [0, 0, 0], [1, 1, 0]]
輸出樣例
[3, 1, 2]
注意:不存在兩個元素大小相等的情況。
我們這題用到了二分插入的思想方法,前半段數列是有序的,雖然這題的關係不存在傳遞性,但我們不難發現,假如a<b那麼a一定能在b的左邊找到一個合適的位置插入,所以我們這題也就迎刃而解。
// Forward declaration of compare API.
// bool compare(int a, int b);
// return bool means whether a is less than b.
class Solution {
public:
vector<int> specialSort(int N) {
vector<int> res;
res.push_back(1);
for(int i=2;i<=N;i++)
{
int l=0,r=res.size()-1;
while(l<r)
{
int mid=l+r>>1;
if(compare(i,res[mid])) r=mid;
else l=mid+1;
}
if(compare(i,res[r])) res.insert(res.begin()+r,i);
else res.insert(res.begin()+r+1,i);
}
return res;
}
};