bzoj_1858_[scoi2010]序列操作_線段樹
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
分析:線段樹處理多個標記。
我這裡是先下傳取反標記,後下傳覆蓋標記。
這樣的話。如果操作是先覆蓋後取反,就在取反的函式中判斷一下,如果有覆蓋就把覆蓋的值取反。
**:
#include #include #include using namespace std;#define n 100050
#define ls p<<1
#define rs p<<1|1
int t[n<<2],cov[n<<2],rev[n<<2],n,m;
int lx[n<<2][2],rx[n<<2][2],nx[n<<2][2],siz[n<<2];
void pushup(int p)
}void build(int l,int r,int p)
int mid=l+r>>1;
build(l,mid,ls);
build(mid+1,r,rs);
pushup(p);
}void pushdown(int p)
if(cov[p]!=-1)
}void uprever(int l,int r,int x,int y,int p)
pushdown(p);
int mid=l+r>>1;
if(x<=mid) uprever(l,mid,x,y,ls);
if(y>mid) uprever(mid+1,r,x,y,rs);
pushup(p);
}void update(int l,int r,int x,int y,int c,int p)
pushdown(p);
int mid=l+r>>1;
if(x<=mid) update(l,mid,x,y,c,ls);
if(y>mid) update(mid+1,r,x,y,c,rs);
pushup(p);
}int qsum(int l,int r,int x,int y,int p)
int qcon(int l,int r,int x,int y,int p)
}int main() else if(opt==1) else if(opt==2) else if(opt==3) else
}}
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 延伸到右區間的情況,右起同理。最大連續考慮左區間的...