NC20279序列操作

2021-10-21 06:51:14 字數 3133 閱讀 5795

輸入:

10 10

0 0 0 1 1 0 1 0 1 1

1 0 2

3 0 5

2 2 2

4 0 4

0 3 6

2 3 7

4 2 8

1 0 5

0 5 6

3 3 9

輸出:52

65思路:核心:線段樹、模擬

首先確定要維護的資訊,要查區間1的數量,最大連續1的長度,又有取反操作(0和1資訊交換)。

所以最好0和1的資訊都要維護。對於0和1我開了個陣列分別存資訊,因為對0和1的操作類似,用個for(0->1)少寫點**~

維護區間0和1的數量,最大連續0和1的長度。

連續長度可能還有出現在區間合併中,所以還要維護區間兩端的0和1向中間連續擴充套件的長度。

還有一些說明在**注釋中談及。

記得向下傳遞lazy標記時,消除自身lazy標記!!!

(挺麻煩的一道線段樹×

#include

#define ios std::ios_base::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);

using

namespace std;

typedef

long

long ll;

const

int n=

100100

;struct ty //線段樹維護的量

tree[

4*n]

;int a[n]

;void

pushup

(int p,

int l,

int r)

}void

build

(int p,

int l ,

int r)

int mid =

(l+r)/2

;build

(p *

2, l, mid)

;build

(p *2+

1, mid+

1, r)

;pushup

(p, l, r);}

void

pushdown

(int p,

int l,

int r)

else

}void

change

(int p,

int l,

int r,

int a,

int b ,

int x)

//區級修改,操作01

if( tree[p]

.lazy !=3)

pushdown

(p,l,r)

;int mid=

(l+r)

>>1;

if( a <= mid )

change(2

*p ,l, mid ,a ,b,x);if

( b > mid )

change(2

*p+1

,mid+

1,r, a ,b ,x)

;pushup

(p,l,r);}

void

revers

(int p,

int l,

int r,

int a ,

int b)

int mid=

(l+r)

>>1;

if( tree[p]

.lazy!=3)

pushdown

(p,l,r);if

( a <= mid )

revers(2

*p ,l, mid ,a ,b);if

( b > mid )

revers(2

*p+1

,mid+

1,r, a ,b)

;pushup

(p,l,r);}

intfindsum

(int p,

int l,

int r,

int x,

int y)

struct ty2

;ty2 findmax

(int p ,

int l,

int r,

int a,

int b)

int mid =

(l+r)/2

;if(tree[p]

.lazy !=3)

pushdown

(p, l, r);if

(b <= mid)

return

findmax

(p*2

, l, mid, a, b);if

(a > mid)

return

findmax

(p*2+1

, mid+

1, r, a, b)

; ty2 left =

findmax

(p*2

, l, mid, a, mid)

; ty2 right =

findmax

(p*2+1

, mid+

1, r, mid+

1, b)

; ans.mx =

max(

max(left.mx, right.mx)

,left.r+right.l);if

(left.l ==

(mid-l+1)

) ans.l = left.l+right.l;

else ans.l = left.l;

if(right.l ==

(r-(mid+1)

+1)) ans.r = left.r+right.r;

else ans.r = right.r;

return ans;

}int

main()

}

BZOJ2962 序列操作

題目大意 給定n個數,要求支援區間加,區間取相反數,區間查詢任意選c c 20 個數的所有方案中乘積的和 和維護k次方的和很像,想要維護選c個數,就要把選1 c個數的方案全部維護出來 這樣當合併兩個區間的時候 pushup 只需要列舉左右區間分別取了幾個數即可 現在考慮兩種修改操作 1.區間取相反數...

bzoj2962 序列操作

有乙個長度為n的序列,有三個操作1.i a b c表示將 a,b 這一段區間的元素集體增加c,2.r a b表示將 a,b 區間內所有元素變成相反數,3.q a b c表示詢問 a,b 這一段區間中選擇c個數相乘的所有方案的和mod 19940417的值。第一行兩個數n,q表示序列長度和操作個數。第...

2017 9 10 序列操作 思考記錄

唉,怎麼說呢 pushdown要注意的事全忘光了 寫 調竟然花了兩個小時 要注意反轉時是 1而不是 1!下傳標記不要單純管順序,因為沒有任何意義,要確保在任意時刻乙個點只有一種同級標記!比如賦值和反轉就是一級的 順序可以換 但加減和乘除是兩級的,因為可以規定先加減再乘除 就不會影響了 碼 為什麼我寫...