題解 HNOI 2016序列

2021-08-17 14:42:15 字數 1793 閱讀 3650

collapse_bzoj

這道題在hnoi2016中還算是好的了……

這題中如若去掉多組詢問的話可以在o(

nlogn)

o (n

log⁡n)

的時間內得解(並查集),但多組詢問必定要優化,發現這種其他結構基本上無法涉足的題目就只能上莫隊了(我也不知道為啥想到莫隊,可能這就是題感吧)減去o

(nn‾

√)o (n

n)

只剩下常數時間可供轉移了,那麼就要想法常數轉移

明顯在乙個序列變化時答案的變化值取決於邊界消長節點與序列中每乙個節點所組成區間的答案,那麼一定只有預處理才能常數解決

考慮乙個數ai

a

i只有在前面第乙個比其小的元素後面,後面第乙個比其小的元素前面的區間才有效,那麼預處理出pr

e[] pre

[]

和nxt[

] nxt

[]

陣列分別表示每個元素前後第乙個比其小的元素的位置,明顯可以用單調棧o(

n)o (n

)解決(不會的看**),再根據這兩個陣列預處理出乙個貢獻字首和與乙個貢獻字尾和,那麼轉移的大體貢獻就可以根據這兩個前/字尾和做差得到

剩下的就只有區間的邊緣部分,邊緣部分只用快速查詢邊緣部分中的最小值即可,如果也要用常數時間查詢,蒟蒻就只知道st表了

#include

using

namespace

std;

typedef

long

long ll;

#define rg register

#define cl(x) memset(x,0,sizeof(x))

#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)>0?(x):(-(x)))

template

inline _tp read(_tp&x)

const

int n=100100;

struct queryqu[n];

ll a[n],suml[n],sumr[n],ans[n];

int st[n][18],log[n],pre[n],nxt[n],sta[n],top(0);

int n,m;

inline

int cmp1(const query&aa,const query&bb)

void init();

void pre_pre_suf();

void pre_st();

void pre_pointer();

void div_block();

void captain_mo()

while(qu[i].l1)+sumr[l]-sumr[pos];}

while(qu[i].r1)+suml[r]-suml[pos];--r;}

while(l1)+sumr[l]-sumr[pos];++l;}

ans[qu[i].id]=ans;

}return ;

}void print();

int main()

void pre_pre_suf()

void print()

void div_block()

void pre_st()

void pre_pointer()

return ;

}void init()

Hnoi2016 序列 解題報告

我們考慮從左往右掃右端點和從右往左掃左端點的兩遍掃瞄線。以下選取從左往右的掃瞄線來說明 考慮每個點向它左邊第乙個比它大的點連邊形成的樹。設i左邊第乙個比它大的點的座標是la sti 如果沒有則la sti 0 i右邊第乙個比它大的點的座標是ne xti 如果沒有則ne xti n 1 設 l,r 的...

HNOI2016 序列(未通過)

題解 雖然知道有點問題但是並沒有debug出來 發現錯誤了。相同元素的處理有錯誤 網上題解大都是分塊。hn怎麼道道分塊 用最普通的思路,可以列舉每個點作為最小值,向左向右延伸 但是多組詢問顯然我們是要去優化詢問過程的 有一種方法就是先找出最大值 其實也可以是隨意乙個位置吧,但yy一下應該最大值能擴充...

Hnoi2016 序列(莫隊 st表)

給定長度為 n n 的序列 a1 role presentation style position relative a1a 1,a2 a 2,an a n,記為a 1 n a 1 n 類似地,a l r a l r 1 l r n 1 l r n 是指序列 al a l,al 1a l 1,ar ...