BZOJ 1500 NOI2005 維修數列 題解

2022-05-22 01:06:08 字數 1837 閱讀 7350

題目大意:要求維護乙個序列,支援插入,刪除,修改(將一段區間內的數全部設定為c),區間翻轉,區間求和,區間最大和。

splay維護。其中區間最大和用乙個mmax值來記錄,需要用lmax和rmax來輔助(代表字首最大和和字尾最大和)。

mmax有三種情況:區間全部在左子樹中,區間全部在右子樹中,區間跨越左右子樹。

lmax有兩種情況:區間全部在左子樹中,區間跨越左右子樹。這樣更新一下即可。

(更新的時候有一些小細節,詳見**)

注意reverse操作。mmax不變,lmax和rmax交換。注意這題因為有附加值,不能像supermemo那題一樣翻轉時只修改標記,下傳的時候再真正修改。

注意操作結束之後要對父親進行maintain維護。(不過在makesame和reverse操作之後不maintain也可以,不知道為什麼)

(不過maintain操作是o(1)的,多maintain幾次沒壞處...)

1 #include2 #include3

const

int maxn=1000000+10;4

const

int inf=~0u>>1;5

inta[maxn];

6struct

node

12 inline void

maintain()

1320 inline void setc(node* t,bool

d)21

25 inline void makesame(int

sv)26

32 inline void

revit()

3338 inline bool d()

39 inline void

pushdown();

40 }tnull,*null=&tnull;

41 inline void

node::pushdown()

4249

if(same)

5055

}56 node*root;

57 inline void rot(node*t)

5869

void splay(node* t,node* f=null)70

76 t->maintain();77}

78 node* select(int

k)7988}

89 inline node*& get(int l,int r) //

[l,r)

9097

void deletetree(node*&t)

98105 node* build(int l,int r) //

[l,r)

106117

void insert(int pos,int

tot)

118128 inline void delete(int pos,int

tot)

129136 inline void makesame(int pos,int tot,int

c)137

144 inline void reverse(int pos,int

tot)

145152 inline int getsum(int pos,int

tot)

153158 inline int

maxsum()

159163

intn,m;

164char s[20

];165

intmain()

166194

}195

return0;

196 }

view code

BZOJ1500 NOI2005 維修數列

description input 輸入檔案的第1行包含兩個數n和m,n表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初始時的數列。以下m行,每行一條命令,格式參見問題描述中的 output 對於輸入資料中的get sum和max sum操作,向輸出檔案依次列印結果,每個...

bzoj1500 NOI2005 維修數列

splay鼻祖級的題目?霧。insert 把第pos個數 有哨兵節點 轉到root,把第pos 1個數轉到root的右兒子,然後對c建樹然後把這棵樹插到root右兒子的左兒子處 delete 把第pos個數轉到root,把第pos tot 1個數轉到root右兒子,刪掉root右兒子的左兒子 變成0...

BZOJ 1500 NOI2005 維修數列

輸入的第1 行包含兩個數n 和m m 20 000 n 表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初始時的數列。以下m行,每行一條命令,格式參見問題描述中的 任何時刻數列中最多含有500 000個數,數列中任何乙個數字均在 1 000,1 000 內。插入的數字總數不...