洛谷P2846 光開關 線段樹

2022-09-03 05:12:12 字數 1836 閱讀 7360

給出乙個01串,每次有兩種操作:

首先,這是一道三倍經驗題。

p2574 xor的藝術

p3870 [tjoi2009]開關

(這兩道題可以用分塊做,但是光開關用分塊會t)

這道題其實就是乙個裸的線段樹。用tre

e[x]

.ltr

ee[x

].l和t

ree[

x].r

tree

[x].

r表示這個區間的左右端點,tre

e[x]

.num

tree

[x].

num表示這個區間有多少個1,tre

e[x]

.laz

ytre

e[x]

.laz

y就是懶惰標記。

其中只有tre

e[x]

.laz

ytre

e[x]

.laz

y和線段樹模板不一樣。由於很明顯如果我們將同乙個區間取反兩次,那麼就是沒有取反的意思。所以,tre

e[x]

.laz

ytre

e[x]

.laz

y其實只要表示這個區間是否被按了奇數次就可以了(按偶數次其實就是按很多個兩次,依舊沒變),所以tre

e[x]

.laz

ytre

e[x]

.laz

y的取值就只會是0或1(0表示按了偶數次,1表示按了奇數次),每次更新時異或1即可。

時間複雜度:o(n

logn

)o(n

logn

)分塊的做法也稍微提一下。可以將這個總區間分成nn​

個小區間,每次直接在每個小區間內更新,與分塊模板也很像。

時間複雜度:o(n

n)o(

nn​)

線段樹模板:

分塊模板:

#include

#define n 1000100

using

namespace std;

int n,m,w,x,y;

struct node

tree[n*3]

;void

make

(int x)

void

pushdown

(int x)

//下傳標記

}int

ask(

int x,

int l,

int r)

//查詢

void

change

(int x,

int l,

int r)

//修改

if(tree[x]

.l==tree[x]

.r)return

;pushdown

(x);

int mid=

(tree[x]

.l+tree[x]

.r)/2;

if(l>mid)

if(r<=mid)

change

(x*2

,l,mid)

;change

(x*2+1

,mid+

1,r)

; tree[x]

.num=tree[x*2]

.num+tree[x*2+

1].num;

//更新每個區間的值

}int

main()

else

}return0;

}

洛谷3870 開關(線段樹)

題意還是很明顯的,支援區間取反,區間查詢。所以我們線段樹的sum陣列開成二維的,第一維記錄關的燈的數量,第二維記錄開著的燈的數量。push down的lazy標記就swap一下0和1的個數。查詢時返回區間1的sum即可。includeusing namespace std const int max...

洛谷 p3870 開關 線段樹模板

這兩天學了很長時間於是做了一道水題 我就用了模板,就連任何優化都沒有 就ac了,複雜度也很 10個點1500多毫秒 這個題就是把lazy改成記錄下修改的次數,每次修改的時候mod 2,因為反過來再返回去就一樣了 修改變成 sum root r l 1 sum root 其他的幾乎就沒區別了 incl...

線段樹2 洛谷p3373 線段樹

題目位址 解釋 多了乙個乘法操作,可以考慮優先順序。每次先算乘法。首先,對於乙個區間 和為s 假設已經按 a 乘b進行了操作。值得到的值為 s a b sb ab 假設先乘得到 sb a 這樣相比,add應該還要再乘上乙個b才對,所以,當更新到乙個區間時,為了進行先乘的操作而不讓結果發生變化,應該將...