POI 2012 Well 二分 單調性

2021-07-03 11:13:56 字數 1792 閱讀 9946

給你乙個長度為

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,...