媽的調了兩天終於過了。。。我好菜啊。
題意
對長度為n的序列執行q種操作,
0:把區間內的值都置為0;
1:把區間內的值都置為1;
2:把區間內的0都置為1,區間內的1都置為0;
3:查詢區間裡1的個數;
4:查詢區間裡最長的連續為1的區間的長度;
題解
顯然,線段樹區間更新區間查詢可解此題,具體是:
維護懶標標記set,區間裡1的個數sum1,區間左端點l,區間右端點r,區間裡最長的連續為1的區間的長度sub,區間裡最長的連續為0的區間的長度zsub,區間裡以左端點為起點的連續為1的區間的長度lsub1,區間裡以左端點為起點的連續為0的區間的長度lsub0,區間裡以又端點為起點的連續為1的區間的長度rsub1,區間裡以右端點為起點的連續為0的區間的長度rsub0,區間裡以左端點為起點的連續為1的區間的長度lsub1。把這十個給維護好就行了呀。
1 #define dbg(x) cout<<#x<<" = "<< (x)<< endl 2 #define IO std::ios::sync_with_stdio(0); 3 #include <bits/stdc++.h> 4 #define iter ::iterator 5 using namespace std; 6 typedef long long ll; 7 typedef pair<ll,ll>P; 8 #define pb push_back 9 #define se second 10 #define fi first 11 #define rs o<<1|1 12 #define ls o<<1 13 const ll inf=0x7fffffff; 14 const int N=1e5+10; 15 struct node{ 16 int sum1,lsub0,lsub1,rsub0,rsub1; 17 int l,r,sub,zsub; 18 int set; 19 }a[N*4]; 20 void push(int o,int l,int r){ 21 int g=r-l+1; 22 int gl=a[ls].r-a[ls].l+1; 23 int gr=a[rs].r-a[rs].l+1; 24 a[o].sum1=a[ls].sum1+a[rs].sum1; 25 a[o].lsub0=a[ls].lsub0; 26 a[o].rsub0=a[rs].rsub0; 27 28 if(a[o].lsub0==gl){ 29 a[o].lsub0+=a[rs].lsub0; 30 } 31 if(a[o].rsub0==gr){ 32 a[o].rsub0+=a[ls].rsub0; 33 } 34 a[o].lsub1=a[ls].lsub1; 35 a[o].rsub1=a[rs].rsub1; 36 if(a[o].lsub1==gl){ 37 a[o].lsub1+=a[rs].lsub1; 38 } 39 if(a[o].rsub1==gr){ 40 a[o].rsub1+=a[ls].rsub1; 41 } 42 a[o].sub=max(a[ls].rsub1+a[rs].lsub1,max(a[ls].sub,a[rs].sub)); 43 a[o].zsub=max(a[ls].rsub0+a[rs].lsub0,max(a[ls].zsub,a[rs].zsub)); 44 } 45 void sw(int o,int l,int r){ 46 int g=r-l+1; 47 a[o].set=1-a[o].set; 48 a[o].sum1=g-a[o].sum1; 49 swap(a[o].lsub0,a[o].lsub1); 50 swap(a[o].rsub0,a[o].rsub1); 51 swap(a[o].sub,a[o].zsub); 52 } 53 void down(int o,int l,int r){ 54 int g=r-l+1; 55 int gl=a[ls].r-a[ls].l+1; 56 int gr=a[rs].r-a[rs].l+1; 57 int x=a[o].set; 58 if(x==-1)return; 59 if(x<2){ 60 a[ls].set=a[rs].set=x; 61 a[ls].lsub1=a[ls].rsub1=a[ls].sum1=a[ls].sub=x?gl:0; 62 a[rs].lsub1=a[rs].rsub1=a[rs].sum1=a[rs].sub=x?gr:0; 63 a[ls].lsub0=a[ls].rsub0=a[ls].zsub=x?0:gl; 64 a[rs].lsub0=a[rs].rsub0=a[rs].zsub=x?0:gr; 65 a[o].set=-1; 66 } 67 else{ 68 a[o].set=-1; 69 int m=(l+r)/2; 70 sw(ls,l,m); 71 sw(rs,m+1,r); 72 } 73 } 74 void build(int o,int l,int r){ 75 a[o].set=-1; 76 if(l==r){ 77 int x; 78 scanf("%d",&x); 79 a[o].l=a[o].r=l; 80 a[o].sum1=a[o].lsub1=a[o].rsub1=a[o].sub=x; 81 a[o].lsub0=a[o].rsub0=a[o].zsub=1-x; 82 return; 83 } 84 int m=(l+r)/2; 85 build(ls,l,m); 86 build(rs,m+1,r); 87 a[o].l=a[ls].l; 88 a[o].r=a[rs].r; 89 push(o,l,r); 90 } 91 void up(int o,int l,int r,int ql,int qr,int k){ 92 int g=r-l+1; 93 int gl=a[ls].r-a[ls].l+1; 94 int gr=a[rs].r-a[rs].l+1; 95 if(l>=ql&&r<=qr){ 96 if(k<2){ 97 a[o].set=k; 98 a[o].lsub1=a[o].rsub1=a[o].sub=a[o].sum1=k?g:0; 99 a[o].lsub0=a[o].rsub0=a[o].zsub=k?0:g; 100 } 101 else sw(o,l,r); 102 return; 103 } 104 down(o,l,r); 105 int m=(l+r)/2; 106 if(ql<=m)up(ls,l,m,ql,qr,k); 107 if(qr>m)up(rs,m+1,r,ql,qr,k); 108 push(o,l,r); 109 } 110 int qu(int o,int l,int r,int ql,int qr,int k){ 111 if(k==3){ 112 if(l>=ql&&r<=qr){ 113 return a[o].sum1; 114 } 115 down(o,l,r); 116 int m=(l+r)/2; 117 int res=0; 118 if(ql<=m)res+=qu(ls,l,m,ql,qr,k); 119 if(qr>m)res+=qu(rs,m+1,r,ql,qr,k); 120 return res; 121 } 122 if(l>=ql&&r<=qr){ 123 return a[o].sub; 124 } 125 down(o,l,r); 126 int m=(l+r)/2; 127 int res=min(a[ls].rsub1,m-ql+1)+min(a[rs].lsub1,qr-m); 128 if(ql<=m)res=max(res,qu(ls,l,m,ql,qr,k)); 129 if(qr>m)res=max(res,qu(rs,m+1,r,ql,qr,k)); 130 return res; 131 } 132 int T,n,q; 133 int main(){ 134 scanf("%d",&T); 135 while(T--){ 136 scanf("%d%d",&n,&q); 137 build(1,1,n); 138 while(q--){ 139 int k,l,r; 140 scanf("%d%d%d",&k,&l,&r); 141 l++; 142 r++; 143 if(k<=2)up(1,1,n,l,r,k); 144 else printf("%d\n",qu(1,1,n,l,r,k)); 145 } 146 } 147 }