給你乙個長度為
n 的序列
a,每次操作可以讓其中乙個數字減1,最多能進行
m 次操作,問要使得存在某個ai
=0的話,max
的最小值是多少
我們可以二分答案,此問題變為判定性問題:問要使得存在某個ai
=0的話,
max 是否可以小於等於mi
d 我們首先要操作幾次,讓整個序列滿足
max 小於等於mi
d 。首先從左到右掃,若出現ai
−ai−
1>mi
d 的情況,ai
就要減去一部分。顯然這樣做之後,就能滿足
max≤mi
d 。然後從右到左掃,若出現ai
−ai+
1>mi
d 的情況,ai
就要減去一部分。顯然這樣做之後,就能滿足
max≤mi
d 。兩次操作後,就能滿足
max≤mi
d 然後我們就需要讓乙個ai
變成0了,某個ai
變成0之後,ai
附近會有連續的一段元素的數字大小都要減少,這個大概yy下可以想得到。記這段區間為[l
i,ri
] ,li
顯然應該滿足:∀j
,aj≤
(i−j
)mid
,ri 也差不多。這個感覺也比較容易想出來,[l
i,ri
] 區間內的所有元素的數字大小都得減少,這個大家自己腦補下吧,我感覺有點難講清楚。。。
這樣,每次都重新找[l
i,ri
] ,總的複雜度是o(
n2lo
gn) 。
但是可以發現,隨著
i 的增加,li
顯然是單調遞增的,隨著
i 的減小,ri
也顯然是單調遞減的,這樣我們可以o(
n)預處理出[l
i,ri
] ,總的複雜度是o(
nlog
n)。
#include
#include
#include
#include
#include
#define maxn 1100000
using
namespace
std;
typedef
long
long
int ll;
int n,a[maxn],b[maxn];
int l[maxn],r[maxn],pos;
ll sum[maxn],m;
bool check(ll limit) //判斷max|}<=limit是否可能
for(int i=n-1;i>=1;i--)
if(b[i]-b[i+1]>limit)
if(cost>m) return
false;
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+b[i];
for(int i=1,j=1;i<=n;i++) //求l
for(int i=n,j=n;i>=1;i--) //求r
for(int i=1;i<=n;i++)
}return
false;
}int main()
else lowerbound=mid+1;
}check(ans);
printf("%d %d\n",pos,ans);
return
0;}
二分(二分答案 二分搜尋)與單調性
經典二分搜尋是二分空間範圍。二分答案又叫二分猜值,是二分解的值空間。其實可以統一,普通的二分搜尋也是二分答案值域 下標空間,也是猜值。二分必須滿足單調性,最直觀的,二分搜尋只能在有序陣列上進行。單調性體現在,下標和元素值是單調的,也就是 if j i 有 a j a i 一般二分答案解決的問題是最優...
二分 單調棧 SPOJ MINSUB
題目 一開始並不會做,然後看了看下面的題解 然後大體思想理解了,之前寫單調棧一直都是用stack,node裡記錄向前延伸向後延伸以及當前的數值和位置,寫這個題的時候覺得用這種方法寫起來比較麻煩,然後嘗試去使用題解中的方法,單調棧可以像這篇題解中使用乙個陣列來模擬棧,同時分兩次遍歷陣列並統計每個元素的...
尋找段落(二分 單調佇列)
題目描述 給定乙個長度為n的序列a i,定義a i 為第i個元素的價值。現在需要找出序列中最有價值的 段落 段落的定義是長度在 s,t 之間的連續序列。最有價值段落是指平均值最大的段落,段落的平均值 段落總價值 段落長度。輸入輸出格式 輸入格式 第一行乙個整數n,表示序列長度。第二行兩個整數s和t,...