洛谷 3512 bzoj 2096 題解

2021-09-17 18:25:52 字數 1758 閱讀 8696

題外話:bzoj2096現在找不到了。。。要交還是上洛谷。。。

給定n,k和乙個長度為n的序列,求最長的最大值最小值相差不超過k的連續序列(翻譯的很清楚)。

輸入:3 9

5 1 3 5 8 6 6 9 10

輸出:4

解釋:5 8 6 6 和 8 6 6 9都是正確的

線段樹+二分長度好像珂以做,但是只能拿80

8080

分,因為n到了3e6

3e63e

6,nlog

nlog

nnlognlogn

nlognl

ogn的做法不太珂靠。所以我們考慮強行套使用單調佇列。

(由於博主剛剛學單調佇列,所以只能強行套)

(考慮到讀者很多也是初學單調佇列,所以我站在了乙個十分好的寫部落格角度。。。)

顯然,要求最大和最小,就要維護兩個優先佇列,取名qxqx

qx和q nqn

qn。(在**中,以x

xx結尾的命名就是和求最大值有關的,以n

nn結尾就是和求最小值有關的)。qxqx

qx要保證單調遞減,那麼qxqx

qx的隊首就是最大值。同理,qnqn

qn要保證單調遞增,那麼qnqn

qn的隊首也就是最小值。以後為了敘述方便,設fxfx

fx為q xqx

qx的隊首,fnfn

fn為q nqn

qn的隊首。

經過一段時間的考慮,我們發現,fx−

fn

>

kfx-fn>k

fx−f

n>

k,那麼我們當前就一定包含了乙個不合法的區間,那麼這兩個隊首肯定有至少乙個要被刪掉。那麼,具體刪哪個呢?

答案是刪在原陣列中位置靠前的。為什麼

意會一下,或者特殊值體會法(我最喜歡用這個方法,代入乙個不那麼具有偶然性的特殊值,然後手動模擬,感受這個選擇的正確性和機智性,學資訊競賽的一定要會用這個方法)

為了方便求出原陣列中的位置,在維護單調佇列的時候,直接存資料的下標,然後判fxfx

fx和f nfn

fn哪個小,刪掉對應的那個。

那麼現在就只剩下合法的區間了。如何計算這個區間的長度呢?

維護乙個pre

prepr

e,表示我們現在考慮到的左端點。初始值是1

11(忘了說了,我們特判a[1

]a[1]

a[1]

,然後後面從2

22開始考慮),在每次彈出隊首的時候要修改為隊首+1(先改再彈,不然資料不對了)。

理一下思路:

(很清楚吧)

**:

#include

#define n 3001000

#define int long long

using

namespace std;

int k,n;

int a[n]

;void

input()

}int qx[n]

,qn[n]

;int hx,tx,hn,tn;

void

solve()

else

} ans=

max(ans,i-pre+1)

;//更新答案

}printf

("%lld\n"

,ans);}

main()

洛谷 模擬題

這道題一直wa?最後看了題解終於過了 include using namespace std typedef long long ll const int ma 10005 int n int a ma 4 intmain int x,y cin x y for int i n 1 i 0 i co...

洛谷簽到題

題目描述 一天 cyx 閒得無聊,寫下了 nn 個數,每個數隻會是 11 或 22,每個數是 11 的概率和是 22 的概率都是 50 50 現在 cyx 想知道他寫的這 nn 個數的和,可他寫的數太多了,他根本算不了,所以他就想知道總和的期望值。你能告訴他麼?輸入格式 乙個整數 nn,表示 cyx...

spfa演算法(洛谷模板題)

一 概況 spfa演算法是常用的最短路演算法之一,複雜度還是非常可觀的。但缺點在於遇到稠密圖或者某些奇特的圖時可能會變慢。spfa演算法是一種單元演算法,選擇乙個出發點,計算它與其他點的最短距離。通過更新邊來不斷更新最短路。在圖論的最短路題中應用十分廣泛。二 過程 1.初始化每個節點到第乙個點的距離...