線段樹 P2253 好乙個一中腰鼓!

2022-05-16 02:36:09 字數 2771 閱讀 7554

傳送門

不得不說 這真是一道不錯的線段樹的題目

這一道題的大意就是說

一開始所有的狀態均為0

會有m次指令

每一次可以把乙個點的狀態進行更改

原來是0就變成1

原來是1就變成0

為了鍛鍊**能力 我決定還是中規中矩地寫線段樹

這一道題還規定了一種串  就是0和1間隔交替 (比如010101  101 01010)

你每一次更改之後 要求出所有的點組成的序列中最長的連續「01」串  

那麼這一道題如果用線段樹來做 轉移會稍微複雜一點

我們定義sum為當前區間最長的01串

lsum為當前區間最長的字首01串

rsum為當前區間最長的字尾01串

那我們怎麼進行轉移呢

先說sum

sum可以是左區間的sum、右區間sum的最大值

也可以是左區間的右半部分(字尾)和右區間的左半部分(字首)  這兩個01串拼起來

當然 這也有一定的條件 必須左半部分的最後乙個字元與右半區間的第乙個字元是不相同的 拼接起來之後才合法

然後lsum怎麼轉移?

首先肯定可以是左半區間的lsum轉移過來

但是還有一種情況

就是如果左半區間整個都是合法的01串(也就是左半區間的字首長度 就等於 整個左半區間的長度)

那麼和起來之後最長的字首01串有可能是整個左半區間+右半區間的字首串  

同樣 這也有一定的條件 就是必須左半區間的最後乙個字元等於右半區間的第乙個字元

rsum則與lsum同理

有可能是右半區間的rsum轉移過來

也有可能是整個右半區間+左半區間的字尾

條件與lsum的類似

這樣子我們就非常完美地建出了一棵線段樹

這樣子我們的解法其實更加高階

題目可以隨便詢問任何乙個區間 我都可以非常自信地回答出該區間內合法的01串的長度

接下來就上我的巨集偉**啦

(其實我也非常驚訝為什麼我10分鐘就做出來了。。一遍ac。。)

//

p2253 好乙個一中腰鼓!

#include#define maxn 20005

using

namespace

std;

intcolor[maxn];

struct

nodet[maxn

<<2

];void build(int p,int l,int

r)

int mid=l+r>>1

; build(p*2

,l,mid);

build(p*2+1,mid+1

,r);

t[p].sum=max(t[p*2].sum,t[p*2+1

].sum);

if(color[t[p*2].r]!=color[t[p*2+1].l]) t[p].sum=max(t[p].sum,t[p*2].rsum+t[p*2+1

].lsum);

t[p].lsum=t[p*2

].lsum;

if(t[p*2].lsum==(t[p*2].r-t[p*2].l+1)&&color[t[p*2].r]!=color[t[p*2+1

].l])

t[p].lsum=max(t[p].lsum,t[p*2].r-t[p*2].l+1+t[p*2+1

].lsum);

t[p].rsum=t[p*2+1

].rsum;

if(t[p*2+1].rsum==(t[p*2+1].r-t[p*2+1].l+1)&&color[t[p*2].r]!=color[t[p*2+1

].l])

t[p].rsum=max(t[p].rsum,t[p*2+1].r-t[p*2+1].l+1+t[p*2

].rsum);

return;}

void change(int p,int l,int r,int

ind)

int mid=l+r>>1

;

if(ind>mid)

change(p*2+1,mid+1

,r,ind);

else change(p*2

,l,mid,ind);

t[p].sum=max(t[p*2].sum,t[p*2+1

].sum);

if(color[t[p*2].r]!=color[t[p*2+1].l]) t[p].sum=max(t[p].sum,t[p*2].rsum+t[p*2+1

].lsum);

t[p].lsum=t[p*2

].lsum;

if(t[p*2].lsum==(t[p*2].r-t[p*2].l+1)&&color[t[p*2].r]!=color[t[p*2+1

].l])

t[p].lsum=max(t[p].lsum,t[p*2].r-t[p*2].l+1+t[p*2+1

].lsum);

t[p].rsum=t[p*2+1

].rsum;

if(t[p*2+1].rsum==(t[p*2+1].r-t[p*2+1].l+1)&&color[t[p*2].r]!=color[t[p*2+1

].l])

t[p].rsum=max(t[p].rsum,t[p*2+1].r-t[p*2+1].l+1+t[p*2

].rsum);

}void

ask()

intmain()

return0;

}

敲之甚急 **凌亂 請見諒

P2253 好乙個一中腰鼓!

話說我大一中的運動會就要來了,據本班同學劇透 其實早就知道了 我萌萌的初二年將要表演腰鼓 噴 這個無厘頭的題目便由此而來。ivan亂入 忽一人大呼 好乙個安塞腰鼓!滿座寂然,無敢譁者,遂與外人間隔。設想一下,腰鼓有兩面,一面是紅色的,一面是白色的。初二的蘇大學神想給你這個oier出一道題。假設一共有...

P2253 好乙個一中腰鼓!

題意 給你乙個序列,初始是0,每次乙個操作,把乙個數 1 每次求出最長01串的長度 正解 線段樹 雖然暴力能過 對於每個區間,記錄三個值 lmax,以l為首的01串長度 rmax,以r為尾的01串長度 mmax,既不以l又不以r為為端點的完全包在區間內的最長01串長度 注意合併!include in...

P2253 好乙個一中腰鼓!

話說我大一中的運動會就要來了,據本班同學劇透 其實早就知道了 我萌萌的初二年將要表演腰鼓 噴 這個無厘頭的題目便由此而來。ivan亂入 忽一人大呼 好乙個安塞腰鼓!滿座寂然,無敢譁者,遂與外人間隔。設想一下,腰鼓有兩面,一面是紅色的,一面是白色的。初二的蘇大學神想給你這個oier出一道題。假設一共有...