洛谷P2048 NOI2010 超級鋼琴 題解

2022-02-13 21:23:33 字數 2162 閱讀 3584

近期發現這篇題解有點爛,更新一下,刪繁就簡,詳細重點。**多加了注釋。就醬紫啦!

我們需要先算美妙度的字首和,並初始化rmq。

迴圈 \(i\) 從 \(1\) 到 \(n\) ,因為以i為起點的和弦終點必定是 \(i + l - 1\) 到 \(i + r - 1\) 之間,所以只要在區間內用rmq取超級和弦,並加入以美妙度從小排到大的優先佇列中。

取出堆頂元素,將美妙度加入 \(ans\) ,並將元素切為從 (當前元素的左邊界 到 當前元素終點 - 1) 和 (\(當前元素終點 + 1 到 當前元素右邊界\)) 兩個部分,並再次加入優先佇列,依次進行 \(k\) 次。

輸出答案即可

為什麼要使用字首和 and rmq?

資料範圍是500000,很明顯,為了優化需要字首和 and rmq。

字首和最明顯的用處,是可以優化乙個用來迴圈累加和的 \(n\) 。而 \(rmq\) ,顯然區間最值符合題目要求。

這兩個演算法詢問答案都是o(1)。字首和後面減去前面,rmq只需要初始化一下,然後o(1)詢問即可。

為什麼第三步要切開元素並放入優先佇列? 直接累加前 \(k\) 個元素不行麼?

首先,我們肯定可以確定:優先佇列中第一大的和弦一定是 \(全域性\) 最大的和弦。 不要問我怎麼證明

那麼優先佇列中第二大的和弦一定是 \(全域性\) 次大的和弦麼?這就不一定了。

所以我們需要切開元素並放入優先佇列,保證每次取出來的元素一定是全域性大小排名的元素

自己拿出紙和筆,結合題解自己思考,在草稿紙上演算一下,就懂了

實在還有問題,私信本人233

#include#include#pragma gcc optimize(2)

#define in(a) a = read()

#define out(a) write(a)

#define outn(a) out(a),putchar('\n')

#define ll long long

#define min(a,b) a < b ? a : b

#define max(a,b) a > b ? a : b

#define rg register

#define new ll

using namespace std;

namespace io_optimization

while(isdigit(ch))

return w ? -x : x;

} inline void write(new x)

#undef new

}using namespace io_optimization;//上面一坨優化的東西不用在意

const int maxn = 500000 + 2;//定義常亮

int n,k,l,r;

int sum[maxn],lg[maxn],dp[maxn][20],pos[maxn][20];

// 字首和 lg2值

//dp[i][j]表示i的2^j次方祖先 pos陣列來記錄最佳位置

ll ans;

struct node };

inline void rmq_init() //預處理

else

}return;

} inline int rmq_query(int l, int r) //返回最值的位置

int main()

rmq_init();//初始化

priority_queuepq; //定義優先佇列

for(rg int i = 1;i + l - 1 <= n; ++i) //計算每個位置最大的超級和弦

for(rg int i = 1;i <= k; ++i) //取k次堆頂的值

if(cur.t < cur.right) //當前取最值的位置 小於 當前和弦的 右邊界

}outn(ans);

return 0;

}

洛谷 P2048 NOI2010 超級鋼琴

給出乙個序列,求和最大的k個連續子串行的和,且連續子串行長度在l與r之間.首先預處理出字首和,我們可以從左端點開始考慮,若左端點為i,則右端點在i l 1與i r 1之間,那麼可以計算出這些區間的最大值,然後放到堆裡去,每次從堆中取出最大值加到ans中後再將該區間左右兩區間的最大值放入堆中.也就是說...

P2048 NOI2010 超級鋼琴

小z是乙個小有名氣的鋼琴家,最近c博士送給了小z一架超級鋼琴,小z希望能夠用這架鋼琴創作出世界上最美妙的 這架超級鋼琴可以彈奏出n個音符,編號為1至n。第i個音符的美妙度為ai,其中ai可正可負。乙個 超級和弦 由若干個編號連續的音符組成,包含的音符個數不少於l且不多於r。我們定義超級和弦的美妙度為...

P2048 NOI2010 超級鋼琴

和十二省聯考d1t2相似的思路 用堆維護最大值,取出乙個位置之後把這個位置的下乙個值插入堆 注意插入的數有負數,並且開long long include include include include define int long long using namespace std struct q...