點擊開啟題目連結,還有一個類似的題,只進行01翻轉操作和最大連續查詢,HDU3911
Black And White
對一個數列進行如下操作:
Change operations:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
區間屬性
1.最大連續長度=Max(左區間最大,有區間最大,左區間右起最大+有區間左起最大)
2.左端點開始的最大連續長度=左區間最大左連續 或 左區間長度+右區間最大左連續(如果左區間最大左連續==左區間長度)
3.有端點開始的最大連續長度,同上;
注意:
1. 所有翻轉的flag都要用 ^操作,避免連續翻轉兩次而未更新的區間。
2.全置的優先順序高於翻轉
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.StreamTokenizer;public class Main{ class SegTree{ class node{ int left,right; int flag,num0,num1; int max0,l0,r0; int max1,l1,r1; int mid(){ return (left+right)>>1; } int length(){ return right-left+1; } void init(int k){ if(k==0){ num0=max0=l0=r0=length(); num1=l1=r1=max1=0; } else { max1=l1=r1=num1=length(); num0=max0=l0=r0=0; } } } node tree[]; SegTree(int maxn){ tree=new node[maxn*5]; } void init(int left,int right,int idx,int[]a){ tree[idx]=new node(); tree[idx].left=left; tree[idx].right=right; tree[idx].flag=-1; if(left==right){ tree[idx].init(a[left]); return; } int mid=tree[idx].mid(); init(left,mid,idx<<1,a); init(mid+1,right,(idx<<1)|1,a); pushup(idx); } void update(int left,int right,int idx,int op){ pushdown(idx); if(tree[idx].left>=left&&tree[idx].right<=right){ if(op==2) reverse(idx); else tree[idx].flag=op; return; } int mid=tree[idx].mid(); if(left<=mid) update(left,right,idx<<1,op); if(right>mid) update(left,right,(idx<<1)|1,op); pushup(idx); } int query(int left,int right,int idx,int type) { pushdown(idx); if(tree[idx].left==left&&tree[idx].right==right){ if(type==3) return tree[idx].num1; else return tree[idx].max1; } int mid=tree[idx].mid(); if(right<=mid) return query(left,right,idx<<1,type); else if(left>mid) return query(left,right,(idx<<1)|1,type); else{ int a=query(left,mid,idx<<1,type); int b=query(mid+1,right,(idx<<1)|1,type); if(type==3) return a+b; int c = Math.min(tree[idx << 1].r1, mid - left + 1) + Math.min(tree[(idx << 1) | 1].l1, right - mid); return Math.max(Math.max(a,b),c); } } void pushup(int idx){ if(tree[idx].left==tree[idx].right) return; pushdown(idx<<1); pushdown((idx<<1)|1); tree[idx].num1=tree[idx<<1].num1+tree[(idx<<1)|1].num1; tree[idx].num0=tree[idx<<1].num0+tree[(idx<<1)|1].num0; int a=tree[idx<<1].max0; int b=tree[(idx<<1)|1].max0; int c=tree[idx<<1].r0+tree[(idx<<1)|1].l0; tree[idx].max0=Math.max(Math.max(a,b), c); tree[idx].l0=tree[idx<<1].l0; if(tree[idx].l0==tree[idx<<1].length()) tree[idx].l0+=tree[(idx<<1)|1].l0; tree[idx].r0=tree[(idx<<1)|1].r0; if(tree[(idx<<1)|1].r0==tree[(idx<<1)|1].length()) tree[idx].r0+=tree[idx<<1].r0; a=tree[idx<<1].max1; b=tree[(idx<<1)|1].max1; c=tree[idx<<1].r1+tree[(idx<<1)|1].l1; tree[idx].max1=Math.max(Math.max(a,b), c); tree[idx].l1=tree[idx<<1].l1; if(tree[idx].l1==tree[idx<<1].length()) tree[idx].l1+=tree[(idx<<1)+1].l1; tree[idx].r1=tree[(idx<<1)|1].r1; if(tree[(idx<<1)|1].r1==tree[(idx<<1)|1].length()) tree[idx].r1+=tree[idx<<1].r1; } void pushdown(int idx){ if(tree[idx].flag==2){ int t=tree[idx].l0; tree[idx].l0=tree[idx].l1; tree[idx].l1=t; t=tree[idx].r0; tree[idx].r0=tree[idx].r1; tree[idx].r1=t; t=tree[idx].max0; tree[idx].max0=tree[idx].max1; tree[idx].max1=t; tree[idx].flag=-1; t=tree[idx].num0; tree[idx].num0=tree[idx].num1; tree[idx].num1=t; if(tree[idx].left!=tree[idx].right){ t=idx<<1; reverse(t); t++; reverse(t); } } if(tree[idx].flag==1||tree[idx].flag==0){ int t=tree[idx].flag; tree[idx].init(t); tree[idx].flag=-1; if(tree[idx].left!=tree[idx].right){ tree[idx<<1].flag=t; tree[(idx<<1)|1].flag=t; } } } void reverse(int idx){ if(tree[idx].flag==2) tree[idx].flag=-1; else if(tree[idx].flag==-1) tree[idx].flag=2; else tree[idx].flag^=1; } } StreamTokenizer in = new StreamTokenizer(new BufferedReader( new InputStreamReader(System.in))); final int next() throws IOException { in.nextToken(); return (int) in.nval; } SegTree st=new SegTree(100010); int a[]=new int[100010]; void run() throws IOException{ int t=next(); while(t-->0){ int n=next(); int m=next(); for(int i=1;i<=n;i++) a[i]=next(); st.init(1, n, 1, a); while(m-->0){ int k=next(); int a=next()+1; int b=next()+1; if(k<3) st.update(a, b, 1, k); else System.out.println(st.query(a, b, 1, k)); } } } public static void main(String[] args) throws IOException { new Main().run(); }}