題解 BZOJ 1251 序列終結者

2021-08-14 09:32:27 字數 1892 閱讀 5766

題目描述 description

給定乙個長度為n的序列,每個序列的元素是乙個整數。要支援以下三種操作:

1.將[l,r]這個區間內的所有數加上v

2.將[l,r]這個區間翻轉,比如1 2 3 4變成4 3 2 1

3.求[l,r]這個區間中的最大值

最開始所有元素都是0。

輸入描述 input description

第一行兩個整數n,m。m為操作個數。 以下m行,每行最多四個整數,依次為k,l,r,v。k表示是第幾種操作,如果不是第1種操作則k後面只有兩個數。

輸出描述 output description

對於每個第3種操作,給出正確的回答。

樣例輸入 sample input

4 4

1 1 3 2

1 2 4 -1

2 1 3

3 2 4

樣例輸出 sample output

2資料範圍及提示 data size & hint

n<=50000,m<=100000。

分析:

bzoj 3223 文藝平衡樹公升級版

與原題不同的是,這裡多了區間加法,區間求最大值

根據原題的思想,我們直接將區間加打上乙個lazy標記延遲更新,放在pushdown一起下傳即可

而區間求最大值在更新size值時一起維護一下就好了(放在update裡面)

記得打lazy標記時可以直接將最大值加上新增lazy標記的大小

每次進行區間操作時,我們只需要將l-1號節點交換到root處,將r+1號節點交換到ch[root][1]處即可保證我們要操作的序列為r+1號節點的左子樹,所以對子樹進行操作即可(有沒有想到線段樹?)

實現:由於我們需要操作l-1和r+1,所以需要增加兩個哨兵節點,將編號推至1~n+2,操作l和r+2即可。並且額外增加乙個lazy陣列表示延遲更新的值,增加乙個mx陣列表示以每個節點為根節點的子樹最大值是多少。這裡發現,像線段樹一樣,操作到哪個節點就將標記全部下傳,將mx在update裡面更新,lazy在pushdown裡面更新。

注意,每次將區間加上x時,mx只需要直接加上x即可,不用重新更新

#include 

using

namespace

std;

#define inf 2100000000

#define maxn 50010

int ch[maxn][2],data[maxn],size[maxn],f[maxn],tag[maxn],lazy[maxn],key[maxn],mx[maxn];

int sz,root,n,m;

int read()

bool get(int x) //return if his father`s right kid is him

void update(int x)

void pushdown(int x)

if(tag[x])

return ;

}void rotate(int x)

void splay(int x,int tar)

int findx(int x)

}}int build(int l,int r,int fa)

int main()

case

2: case

3: }

}return

0;}

bzoj 1251 序列終結者

題目在這裡 這應該是splay裸題了吧。對於每個節點儲存5個值,size,max,flag,lazy,val 分別表示這個節點的子樹大小,子樹的最大值,子樹是否有打過翻轉標記,子樹的增加的值,前面的所有都包括這個節點它自己 以及這個節點的當前值。對於一段區間 l,r 的詢問 修改,只需把l 1這個節...

bzoj1251 序列終結者

time limit 20 sec memory limit 162 mb submit 2971 solved 1188 submit status discuss 網上有許多題,就是給定乙個序列,要你支援幾種操作 a b c d。一看另一道題,又是乙個序列 要支援幾種操作 d c b a。尤其是...

BZOJ 1251 序列終結者

網上有許多題,就是給定乙個序列,要你支援幾種操作 a b c d。一看另一道題,又是乙個序列,要支援幾種操作 d c b a。尤其是我們這裡的某人,出模擬試題,居然還出了一道這樣的,真是沒技術含量 這樣,我也出一道題,我出這一道的目的是為了讓大家以後做這種題目有乙個 庫 可以依靠,沒有什麼其他的意思...