SHOI2015 腦洞治療儀 題解 (線段樹)

2022-03-26 10:15:35 字數 1874 閱讀 4466

題目鏈結

題目大意:給定乙個只含$0$和$1$的序列。有三種操作:1.把$[l,r]$內所有數改為$0$;2.把$[l,r]$內所有$1$拿走來填$[l',r']$內所有$0$。多了丟掉,少了優先從左開始填;3.查詢$[l,r]$內最長的$0$串。

一眼能看出來考最大子段和。但是**好難調啊qaq

對於一段序列,我們要維護$4$個東西:$ls,rs,ms,s$,分別為從左端點開始最長的$0$串,從右端點開始最長的$0$串,序列內最長的$0$串,序列和。

維護最大子段和,無非就兩種情況:跨過$mid$和沒有跨過$mid$。注意在維護$ms$的時候有三種情況:左兒子的$ms$,右兒子的$ms$,左兒子$rs$加右兒子$ls$。也可以翻我之前的部落格。

對於區間修改我們維護乙個$lazy$,在$pushdown$的時候維護一下序列就好。

最後說一下$2$操作。我們注意到在一段序列內的和是非嚴格單調遞增的。所以要確定我們填的這個區間,我們只需二分一下這個右端點即可。

然後就是噁心人的調**時間了。壓過行後也有130行……

時間複雜度$o(n\log^2 n)$

**:

#includeusing

namespace

std;

const

int maxn=200005

;int

n,m;

struct

node

tree[maxn*4

];inline

intread()

while(isdigit(ch))

return x*f;

}inline

void pushup(int

index)

inline

void build(int index,int l,int

r)

int mid=(l+r)>>1

; build(index*2

,l,mid);

build(index*2+1,mid+1

,r);

pushup(index);

}inline

void pushdown(int index,int l,int r)//

ms,ls,rs,s,lazy

if (tree[index].lazy==1

)

tree[index].lazy=-1;}

inline

void update(int index,int l,int r,int ql,int qr,int

k) pushdown(index,l,r);

int mid=(l+r)>>1

;

if (ql<=mid) update(index*2

,l,mid,ql,qr,k);

if (qr>mid) update(index*2+1,mid+1

,r,ql,qr,k);

pushup(index);

}inline

int querysum(int index,int l,int r,int ql,int

qr)inline

int queryrest(int index,int l,int r,int ql,int

qr)inline

int querymax(int index,int l,int r,int ql,int

qr)

return

res;

}inline

void work(int l0,int

r0) update(

1,1,n,l1,ans,1);}

intmain()

return0;

}

SHOI2015 腦洞治療儀

我太sb啦 合併的時候又漏了,又漏了,又漏了 我個sb 這是個板子題,並不知道為什麼shoi2015會考這麼板子的題,但是我又sb了,又sb了,又sb了,又沒有1a 顯然我是涼了 這道題有三個操作 區間清零 將乙個區間清零,之後補到另乙個區間去,但是有可能補不滿 詢問乙個區間內最大全零子串 顯然這都...

SHOI2015 腦洞治療儀

嘟嘟嘟 這題其實就是乙個線段樹維護最大連續和的水題。別的操作不說,操作1只要二分找區間前 k 個0即可。需要注意的是,因為操作1兩區間可能有交,因此要先清空再二分查詢 複雜度 o n log 2 n include include include include include include in...

SHOI2015 腦洞治療儀

洛谷題目鏈結 珂朵莉樹吼啊!對於操作 0 其實就是區間賦值為 0 的操作,直接套模板就行了 對於操作 1 應該是這個題目最難的操作了 雖然還是很簡單 我們先查詢 l 0,r 0 這個區間的 1 的數量,最後掃一遍 l 1,r 1 這個區間,如果 1 的數量夠的話直接更改區間值,如果不夠的話就把其中夠...