poj2018 斜率數形結合

2021-07-23 02:22:58 字數 1226 閱讀 7144

題意:給定乙個長度為n的陣列,求其中長度大於等於k的連續的一段,使其算數平均值最大。輸出最大平均值*1000取整的結果。

斜率斜率斜率。。大致感覺可以用斜率來做。。我試了試把最優決策的選擇化成斜率的式子,但發現這本來就是斜率的式子,於是就不知道怎麼弄了。。何老師講的類似分數規劃的方法來做。。但是我覺得斜率也應該可行,就上黑板去楚了三個點點,大致說清楚了上凸包的中間的乙個點對於最後的答案不會有任何貢獻。。然後何老師就讓我下來寫一下。。

正兒八經的題解:處理成字首和,然後將下標作為x軸,字首和作為y軸,兩個下標之間的平均值就對應了這兩個點之間的斜率,求最大的斜率即可。在草稿紙上畫三個形成上凸包的點,兩兩之間連線,把平面分成三個區域,每個區域中的點的最大斜率的決策點要麼是這三個點中最左邊的,要麼是最右邊的,也就是說在上凸包上的點永遠不可能有貢獻。

那麼按照斜率優化的做法,單調佇列維護一下就行了。單調佇列儲存好的就是乙個斜率遞增的曲線,找到這個曲線和新加入的點的切線斜率即是最優值。每相鄰兩個點之間的斜率減去到新加入的點的斜率的值是遞增的,最接近零的就是切線了,所以可以二分查詢。實際過程中發現這個切點永遠會比上一次的切點靠右,於是對對首進行單調操作即可均攤o(1)實現。

上學期和暑假做了一些斜率優化的題,都是按照模式進行的,沒怎麼真正理解。這次碰到斜率優化的鼻祖題,感覺那些比較複雜的操作模式反而不好針對這個太原始的題了,於是就用最原始的辦法來推了一下。。於是我大致想明白為什麼以前那些斜率優化可以直接毫不顧忌地刪對首刪隊尾了。。

#include#include#include#include#includeusing namespace std;

int n,f;

int sum[100005];

int q[100005],l,r;

double xielv(int i,int j)

int main()

double ans=0;

l=1,r=0;

q[++r]=0;//注意斜率優化0這個許多情況一塊加進去

for (int i=f;i<=n;i++)

ans=ans*1000;

int t=ans;

printf("%d",t);

return 0;

}

總結1:這題想到用斜率試一下了,但是常規方法推不出來,實際上發現他本身就是乙個斜率的表示方法,然後分析得知,其滿足下凸包的性質,並且決策也有單調性(這個證明沒有學會),好題,便於對斜率的數形結合方法的理解。

2:

POJ 2018 斜率優化DP

給一堆數,選不少於f個數的子串行,求均值最大的子串行。最原始的斜率dp優化題目,最初出現在周源的國家隊 中。儘管這個題是最原始的題,但是這個題並不能用常用的套路。這個題的狀態轉移方程很明顯,但是卻不是標準的斜率優化方程 當然也差不多 優化的話,基本上還是老套路,用乙個單調佇列進行優化。在選擇最優元素...

poj2018(高精度二分 dp)

題意 給你n個數,要你在這n個數裡面找到一些連續的數,這些數的數量大於等於m,並且他們的平均值在這n個數裡面是最大的.思路 先把n個數的最大最小值確定,然後二分列舉平均值,對於每乙個連續數,只要他們減去平均值大於0,就調製上限制,不然調整下限制,include include includeusin...

poj2018(高精度二分 dp)

題意 給你n個數,要你在這n個數裡面找到一些連續的數,這些數的數量大於等於m,並且他們的平均值在這n個數裡面是最大的.思路 先把n個數的最大最小值確定,然後二分列舉平均值,對於每乙個連續數,只要他們減去平均值大於0,就調製上限制,不然調整下限制,include include includeusin...