洛谷 P4597 序列sequence

2021-10-03 16:17:58 字數 1717 閱讀 8614

此題的弱化版

和這個思路很相似

#include

#define int long long

using

namespace std;

int n,x,ans;

priority_queue<

int>q;

/*題解們都說:考慮當前的數x和之前的最大數y(預設x=y已經滿足非降了)

為了讓它非降,我們要做區間[x,y]裡找到乙個數z,使得y減小到z,x增大到z。

那麼可以發現,無論z取什麼,代價都是y-x。

不難看出,y減小的越多,後面的序列越容易變成非降,那麼只要讓y減小到x就好了。

看到這裡,我一直有乙個疑問,如果令y減小到x之後,序列不滿足非降了怎麼辦?

仔細想了想,實際上應該是這樣的:

為了讓序列非降,y不能小於y之前的最大值。

而由於y是整個序列的最大值,如果它之前的最大值z小於等於x,那麼將y減小到x仍能保證序列是非降的。

否則的話,z大於x小於y,仍是在區間[x,y]內,那麼移動的代價是y-x,所以用於更新答案是沒有問題的

那麼這裡為什麼要讓yy減到最小呢?

這是因為x和y不論如何調整,他們的代價之和都已經不變了,但問題是他們目前選的最優方案並不是之後的最優。

為了滿足他們在之後最優,只有把y減小到x,才能保證之後更有可能非降。

概括一下,對於當前的數,無論最優解如何,對答案的貢獻是一定的。

而為了保證之後的解也最優,令y減小到x,可以保證之後的解最優,且不會影響當前的最優解

-----by 義烏中學 bzt

看了他的部落格後,我覺得他的這個疑問就是我的疑問:如果令y減小到x之後,序列不滿足非降了怎麼辦?

但是看了他的解釋後,我覺得還是沒有解釋到位。

我們假設,第乙個數是5,第二個數是7,第三個數是2

那麼這時候,可以發現:上文中的z就是5,y就是7,x就是2,按照題目意思,我們需要把y變成2,ans+=(7-2)

這時候發現 這個序列不是非降了

那麼怎麼辦呢?

1.如果此時序列已經結束了,那麼我們可以把z變為5,y變為5,x變為5,ans+=5,不需要按照題目要求變化

2.如果此時序列沒有結束,那麼讀入下乙個數d,比如下乙個數是d=3,

按照題目意思,我們需要把z變為3,ans+=(5-3),ans=7 然後堆中的元素為 3,2,2,3

那麼這時候,我們可以把資料變為: z=5-2=3 y=7-4=3 x=2+1=3 d=3 ans=7

雖然我完全沒有按照題意的要求構造數,但是ans還是最小,等於7

也就是可以這樣理解,已經讀入的數相當於成立了乙個強大的聯盟,只需要花費按照**中的代價

那麼無論後面出現哪個數,都可以通過花費**中公式計算出的代價構造出乙個 陣列

使得這個陣列是非降的 !!!

夠強大吧!!!

也就是說,當前堆中的這些size個元素,並不是真正的最後的序列的前面的size個元素 ,而是乙個虛擬的!!!

所以,根本不會出現這個疑問: 如果令y減小的x之後,序列不滿足非降了怎麼辦?

這個思想,和 o(nlogn) 的lis的 b陣列 很相似 !!!

*/signed

main()

}printf

("%lld\n"

,ans)

;return0;

}

洛谷 P1645 序列

炒雞明顯的貪心題,主要就想讓一段區間與另一段裡面重合的數越多越好。於是先按照區間右端排序,然後盡可能的把數都往右靠攏,最後與另一段區間的前面的重合。然後可以用個flag來記錄哪些數被選了什麼的。include includeusing namespace std const int maxn 100...

洛谷 P1631 序列合併

題目描述 有兩個長度都是n的序列a和b,在a和b中各取乙個數相加可以得到n 2個和,求這n 2個和中最小的n個。輸入輸出格式 輸入格式 第一行乙個正整數n 第二行n個整數ai,滿足ai ai 1且ai 10 9 第三行n個整數bi,滿足bi bi 1且bi 10 9.資料規模 對於50 的資料中,滿...

洛谷 P1631 序列合併

有兩個長度都是n的序列a和b,在a和b中各取乙個數相加可以得到n 2個和,求這n 2個和中最小的n個。第一行乙個正整數n 第二行n個整數ai,滿足ai ai 1且ai 10 9 第三行n個整數bi,滿足bi bi 1且bi 10 9.輸出僅一行,包含n個整數,從小到大輸出這n個最小的和,相鄰數字之間...