lxhgww最近收到了一個01序列,序列裏面包含了n個數,這些數要麼是0,要麼是1,如今對於這個序列有五種變換操做和詢問操做:c++
0 a b 把[a, b]區間內的全部數全變成0程序員
1 a b 把[a, b]區間內的全部數全變成1ide
2 a b 把[a,b]區間內的全部數所有取反,也就是說把全部的0變成1,把全部的1變成0ui
3 a b 詢問[a, b]區間內總共有多少個1spa
4 a b 詢問[a, b]區間內最多有多少個連續的1input
對於每一種詢問操做,lxhgww都須要給出回答,聰明的程序員們,大家能幫助他嗎?it
輸入格式:class
輸入數據第一行包括2個數,n和m,分別表示序列的長度和操做數目date
第二行包括n個數,表示序列的初始狀態程序
接下來m行,每行3個數,op, a, b,(0<=op<=4,0<=a<=b<n)表示對於區間[a, b]執行標號爲op的操做
輸出格式:
對於每個詢問操做,輸出一行,包括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
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<n)表示對於區間[a, b]執行標號爲op的操做
輸出格式:
對於每個詢問操做,輸出一行,包括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 9
5 2 6 5
這些操做都比較簡單 以前都學過
可是加在一塊兒就會產生一個問題 那就是翻轉標記和區間修改標記的順序該如何處理 先反轉和先修改的操做是不同的
修改操做的優先級是比翻轉操做的優先級高的
在update裏
對一個點前後兩次操做一共有四種方法
1.先反轉後修改
顯然 翻轉的操做已經被覆蓋掉了 因此在設置修改懶標記的時候若是有翻轉標記直接清空掉
2.先修改後翻轉
正常處理
3.4沒有問題
在down裏
先處理修改的 由於修改的優先級高(先反轉後修改的操做已經被覆蓋掉了 也就是反轉標記已經被清零)
下推懶標記的時候若是下面的兩個兒子有翻轉標記的話要清空
而後處理翻轉標記便可
很是好的線段樹 加深了理解
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 #define CLR(A,v) memset(A,v,sizeof A) typedef pair<int,int>pii; ////////////////////////////////// const int N=1e5+10; int tsum[N<<2],t0[N<<2],t1[N<<2],ri0[N<<2],ri1[N<<2],le0[N<<2],le1[N<<2],len[N<<2],col[N<<2],rev[N<<2]; int num[N]; void up(int pos) { tsum[pos]=tsum[pos<<1]+tsum[pos<<1|1];// 區間求和 t0[pos]=max( max(t0[pos<<1],t0[pos<<1|1]),ri0[pos<<1]+le0[pos<<1|1] ); t1[pos]=max( max(t1[pos<<1],t1[pos<<1|1]),ri1[pos<<1]+le1[pos<<1|1] ); if(le1[pos<<1]==len[pos<<1]) le1[pos]=le1[pos<<1]+le1[pos<<1|1]; else le1[pos]=le1[pos<<1]; if(le0[pos<<1]==len[pos<<1]) le0[pos]=le0[pos<<1]+le0[pos<<1|1]; else le0[pos]=le0[pos<<1]; if(ri1[pos<<1|1]==len[pos<<1|1]) ri1[pos]=ri1[pos<<1|1]+ri1[pos<<1]; else ri1[pos]=ri1[pos<<1|1]; if(ri0[pos<<1|1]==len[pos<<1|1]) ri0[pos]=ri0[pos<<1|1]+ri0[pos<<1]; else ri0[pos]=ri0[pos<<1|1]; } void build(int l,int r,int pos) { len[pos]=r-l+1; if(l==r){ tsum[pos]=num[l]; le0[pos]=ri0[pos]=t0[pos]=(num[l]==0); le1[pos]=ri1[pos]=t1[pos]=(num[l]==1); return ;} int m=(l+r)>>1;build(lson);build(rson);up(pos); } void down(int m,int pos) { if(col[pos]!=-1)// 修改會覆蓋翻轉 { rev[pos<<1]=rev[pos<<1|1]=0;//覆蓋翻轉 col[pos<<1]=col[pos<<1|1]=col[pos];//標記傳遞 if(col[pos]==1){ t1[pos<<1]=tsum[pos<<1]=le1[pos<<1]=ri1[pos<<1]=len[pos<<1]; t1[pos<<1|1]=tsum[pos<<1|1]=le1[pos<<1|1]=ri1[pos<<1|1]=len[pos<<1|1]; t0[pos<<1]=t0[pos<<1|1]=le0[pos<<1]=le0[pos<<1|1]=ri0[pos<<1]=ri0[pos<<1|1]=0;} else if(col[pos]==0){ t0[pos<<1]=le0[pos<<1]=ri0[pos<<1]=len[pos<<1]; t0[pos<<1|1]=le0[pos<<1|1]=ri0[pos<<1|1]=len[pos<<1|1]; tsum[pos<<1]=tsum[pos<<1|1]=le1[pos<<1]=le1[pos<<1|1]=ri1[pos<<1]=ri1[pos<<1|1]=t1[pos<<1]=t1[pos<<1|1]=0;} col[pos]=-1; } if(rev[pos]) { tsum[pos<<1]=len[pos<<1]-tsum[pos<<1]; tsum[pos<<1|1]=len[pos<<1|1]-tsum[pos<<1|1]; swap(le1[pos<<1],le0[pos<<1]); swap(le1[pos<<1|1],le0[pos<<1|1]); swap(ri1[pos<<1],ri0[pos<<1]); swap(ri1[pos<<1|1],ri0[pos<<1|1]); swap(t1[pos<<1],t0[pos<<1]); swap(t1[pos<<1|1],t0[pos<<1|1]);//翻轉01最大連續長度 rev[pos<<1]^=1;rev[pos<<1|1]^=1; rev[pos]=0; } } void upsum(int L,int R,int v,int l,int r,int pos) { if(L<=l&&r<=R) { col[pos]=v;rev[pos]=0;tsum[pos]=v*(r-l+1); t1[pos]=le1[pos]=ri1[pos]=v*(r-l+1); t0[pos]=le0[pos]=ri0[pos]=(v^1)*(r-l+1); return ; }int m=(l+r)>>1;down(r-l+1,pos); if(L<=m)upsum(L,R,v,lson);if(R>m)upsum(L,R,v,rson);up(pos); } void uprev(int L,int R,int l,int r,int pos) { if(L<=l&&r<=R) { rev[pos]^=1; tsum[pos]=r-l+1-tsum[pos]; swap(t1[pos],t0[pos]); swap(le1[pos],le0[pos]); swap(ri1[pos],ri0[pos]); return ; }int m=(l+r)>>1;down(r-l+1,pos); if(L<=m)uprev(L,R,lson);if(R>m)uprev(L,R,rson);up(pos); } int qsum(int L,int R,int l,int r,int pos) { if(L<=l&&r<=R)return tsum[pos]; int ans=0;int m=(l+r)>>1;down(r-l+1,pos); if(L<=m)ans+=qsum(L,R,lson);if(R>m)ans+=qsum(L,R,rson); return ans; } int qmax(int L,int R,int l,int r,int pos) { if(L<=l&&r<=R)return t1[pos]; int m=(l+r)>>1; down(r-l+1,pos); if(L<=m&&R>m) { int ans=max(qmax(L,R,lson),qmax(L,R,rson)),rm,lm; rm=min((m-L+1),ri1[pos<<1] ); lm=min((R-m),le1[pos<<1|1]); ans=max(ans,rm+lm);return ans; } else if(L<=m)return qmax(L,R,lson); else if(R>m)return qmax(L,R,rson); } int n,m,a,b,c; int main() { CLR(col,-1); RII(n,m); rep(i,1,n)RI(num[i]); build(1,n,1); while(m--) { RIII(c,a,b);a++,b++; if(c==0)upsum(a,b,0,1,n,1); if(c==1)upsum(a,b,1,1,n,1); if(c==2)uprev(a,b,1,n,1); if(c==3)printf("%d\n",qsum(a,b,1,n,1)); if(c==4)printf("%d\n",qmax(a,b,1,n,1)); } return 0; }
0 5 6 3 3 9
5 2 6 5