BZOJ1858 Scoi2010 序列操作

2022-02-05 23:58:23 字數 2992 閱讀 9675

lxhgww最近收到了乙個01序列,序列裡面包含了n個數,這些數要麼是0,要麼是1,現在對於這個序列有五種變換操作和詢問操作: 0 a b 把[a, b]區間內的所有數全變成0 1 a b 把[a, b]區間內的所有數全變成1 2 a b 把[a,b]區間內的所有數全部取反,也就是說把所有的0變成1,把所有的1變成0 3 a b 詢問[a, b]區間內總共有多少個1 4 a b 詢問[a, b]區間內最多有多少個連續的1 對於每一種詢問操作,lxhgww都需要給出回答,聰明的程式設計師們,你們能幫助他嗎?

輸入資料第一行包括2個數,n和m,分別表示序列的長度和運算元目 第二行包括n個數,表示序列的初始狀態 接下來m行,每行3個數,op, a, b,(0 < = op < = 4,0 < = a < = b)

對於每乙個詢問操作,輸出一行,包括1個數,表示其對應的答案

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 952

65對於30%的資料,1<=n, m<=1000 對於100%的資料,1< = n, m < = 100000

day2

wa。。。這個神題除錯了我一晚上。

維護區間...貌似都有區間可加性..線段樹!

維護區間$1$的個數,從左端點開始的最長的1/0的個數,從右端點開始最長的1/0的個數。

區間中最長一段的1/0.

然後這題坑的就是標記的下傳。

我們發現區間修改可以覆蓋區間翻轉,就是我們在$change$和$pushdown$的時候,如果這個節點被新修改,就抹去它的翻轉標記。

然後$opt=4$的查詢不好處理,我們要傳下去乙個結構體,裡面存和線段樹節點一樣的東西,然後邊遞迴邊修改。

#include #include 

using

namespace

std;

#define reg registerinline

char

gc()

#define gc getcharinline

intread()

#define n 100005

intn, m;

#define ls o << 1

#define rs o << 1 | 1

inta[n];

int tr[n<<2], l1[n<<2], r1[n<<2], l0[n<<2], r0[n<<2], mx1[n<<2], mx0[n<<2

];int rev[n<<2], lzy[n<<2

];inline

void pushup(int o, int l, int

r)//

lzy : 0 means none , 1 means turn to 1, 2 means turn to 0

//rev : 1 means reverse, 0 means none

//lzy first ans rev second

void pushdown(int o, int l, intr)

else

if (lzy[o] == 2

)

if(rev[o])

}void build(int l, int r, int

o)

int mid = l + r >> 1

; build(l, mid, ls);

build(mid + 1

, r, rs);

pushup(o, l, r);

}void change(int l, int r, int o, int ql, int qr, int

opt)

if (opt == 1

)

if (opt == 2

)

return

; }

pushdown(o, l, r);

int mid = l + r >> 1

;

if (ql <=mid) change(l, mid, ls, ql, qr, opt);

if (qr > mid) change(mid + 1

, r, rs, ql, qr, opt);

pushup(o, l, r);

}int query1(int l, int r, int o, int ql, int

qr)struct

node ;

node query2(

int l, int r, int o, int ql, int

qr);

pushdown(o, l, r);

int mid = l + r >> 1

;

if (qr <= mid) return

query2(l, mid, ls, ql, qr);

if (ql > mid) return query2(mid + 1

, r, rs, ql, qr);

node r1, r2, res;

r1 = query2(l, mid, ls, ql, qr), r2 = query2(mid + 1

, r, rs, ql, qr);

res.tr = r1.tr +r2.tr;

res.mx = max(r1.mx, max(r2.mx, r1.r1 +r2.l1));

res.l1 = r1.l1 + (r1.l1 == mid - l + 1 ? r2.l1 : 0

); res.r1 = r2.r1 + (r2.r1 == r - mid ? r1.r1 : 0

);

return

res;

}int

main()

return0;

}

bzoj1858SCOI 序列操作 (線段樹)

題目大意 給定乙個長度為n的01序列為,現在有m種操作 0a b 0ab 把 a,b a,b 的數全部修改為0 1a b 1ab 把 a,b a,b 的數全部修改為1 2a b 2ab 把 a,b a,b 的所有數取反,就是0 1 1 0 3a b 3ab 詢問 a b a,b 中一共有多少個0 4...

bzoj1858SCOI 序列操作 (線段樹)

題目大意 給定乙個長度為n的01序列為,現在有m種操作 0 a b 把 a,b 的數全部修改為0 1 a b 把 a,b 的數全部修改為1 2 a b 把 a,b 的所有數取反,就是0 1 1 0 3 a b 詢問 a,b 中一共有多少個0 4 a b 詢問 a,b 中最長有多少個連續的1 其中 n...

bzoj1858 Scoi2010 序列操作

bzoj1858 scoi2010 序列操作 一道裸線段樹。的確是比較好想,然而 寫得莫名醜,於是調了很長時間。題解 維護區間中1的總數,左起連續1的個數,右起連續1的個數,最大連續1的個數,0同理。更新的時候左起連續1 0 要考慮左區間全為1 0 延伸到右區間的情況,右起同理。最大連續考慮左區間的...