HDU 3397(线段树,较难~)

Sequence operation

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 927    Accepted Submission(s): 259

Problem Description
lxhgww got a sequence contains n characters which are all '0's or '1's.
We have five operations here:
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]
 

 

Input
T(T<=10) in the first line is the case number.
Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
The next line contains n characters, '0' or '1' separated by spaces.
Then m lines are the operations:
op a b: 0 <= op <= 4 , 0 <= a <= b < n.
 

 

Output
For each output operation , output the result.
 

 

Sample Input
   
   
   
   
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
 

 

Sample Output
   
   
   
   
5 2 6 5
/*看了好几个大牛的代码,学习思路,然后自己敲 手都敲酸了~~~~ @-@ 线段树恐惧症 前几次不是WA就是TLE~~ 最后全删了又继续敲,总共花了1天半的时间~~~*/ #include <iostream> using namespace std; #define N 100010 #define max(a,b) (a>b?a:b) #define min(a,b) (a>b?b:a) struct LineTree { int l,r,mid,len; int count0,left0,right0,max0; int count1,left1,right1,max1; bool fill0,fill1,change; }tree[N*3]; int val[N]; void Update(int root) { tree[root].count0 = tree[root<<1].count0 + tree[(root<<1)+1].count0; tree[root].count1 = tree[root<<1].count1 + tree[(root<<1)+1].count1; tree[root].max0 = max( max(tree[root<<1].max0,tree[(root<<1)+1].max0),tree[root<<1].right0 + tree[(root<<1)+1].left0 ); tree[root].max1 = max( max(tree[root<<1].max1,tree[(root<<1)+1].max1),tree[root<<1].right1 + tree[(root<<1)+1].left1 ); tree[root].left0 = tree[root<<1].left0; tree[root].right0 = tree[(root<<1)+1].right0; if(tree[root<<1].left0 == tree[root<<1].len) tree[root].left0 += tree[(root<<1)+1].left0; if(tree[(root<<1)+1].right0 == tree[(root<<1)+1].len) tree[root].right0 += tree[root<<1].right0; tree[root].left1 = tree[root<<1].left1; tree[root].right1 = tree[(root<<1)+1].right1; if(tree[root<<1].left1 == tree[root<<1].len) tree[root].left1 += tree[(root<<1)+1].left1; if(tree[(root<<1)+1].right1 == tree[(root<<1)+1].len) tree[root].right1 += tree[root<<1].right1; } void Build(int root,int a,int b) { tree[root].l=a; tree[root].r=b; tree[root].mid=(a+b)>>1; tree[root].len=b-a; tree[root].fill0 = tree[root].fill1 = tree[root].change = 0; if(a+1 == b) { tree[root].left0 = tree[root].right0 = tree[root].count0 = tree[root].max0 = 0; tree[root].left1 = tree[root].right1 = tree[root].count1 = tree[root].max1 = 0; if(val[a]) tree[root].left1 = tree[root].right1 = tree[root].count1 = tree[root].max1 = 1; else tree[root].left0 = tree[root].right0 = tree[root].count0 = tree[root].max0 = 1; return; } Build(root<<1,a,tree[root].mid); Build((root<<1)+1,tree[root].mid,b); Update(root); } void Fill0(int root) { tree[root].count0 = tree[root].max0 = tree[root].left0 = tree[root].right0 = tree[root].len; tree[root].count1 = tree[root].max1 = tree[root].left1 = tree[root].right1 = 0; tree[root].fill0 = 0; if(tree[root].len == 1) return; tree[root<<1].fill0 = tree[(root<<1)+1].fill0 = 1; tree[root<<1].fill1 = tree[(root<<1)+1].fill1 = 0; tree[root<<1].change = tree[(root<<1)+1].change = 0; } void Fill1(int root) { tree[root].count1 = tree[root].max1 = tree[root].left1 = tree[root].right1 = tree[root].len; tree[root].count0 = tree[root].max0 = tree[root].left0 = tree[root].right0 = 0; tree[root].fill1 = 0; if(tree[root].len == 1) return; tree[root<<1].fill0 = tree[(root<<1)+1].fill0 = 0; tree[root<<1].fill1 = tree[(root<<1)+1].fill1 = 1; tree[root<<1].change = tree[(root<<1)+1].change = 0; } void Change(int root) { swap(tree[root].count0,tree[root].count1); swap(tree[root].left0,tree[root].left1); swap(tree[root].right0,tree[root].right1); swap(tree[root].max0,tree[root].max1); tree[root].change = 0; if(tree[root].len == 1) return; tree[root<<1].change ^= 1; tree[(root<<1)+1].change ^= 1; } void Down(int root) { if(tree[root].fill0) Fill0(root); if(tree[root].fill1) Fill1(root); if(tree[root].change) Change(root); } void Oper(int root,int a,int b,int x) { Down(root); if(a == tree[root].l && b == tree[root].r) { if(x == 0) tree[root].fill0 = 1; else if(x == 1) tree[root].fill1 = 1; else tree[root].change ^= 1; Down(root); return; } if( b <= tree[root].mid ) Oper(root<<1,a,b,x); else if( tree[root].mid <= a) Oper((root<<1)+1,a,b,x); else { Oper(root<<1,a,tree[root].mid,x); Oper((root<<1)+1,tree[root].mid,b,x); } Down(root<<1); Down((root<<1)+1); Update(root); } int Onenum(int root,int a,int b) { Down(root); if(a == tree[root].l && b == tree[root].r) { return tree[root].count1; } if(b <= tree[root].mid) return Onenum(root<<1,a,b); else if( tree[root].mid <= a) return Onenum((root<<1)+1,a,b); else { return Onenum(root<<1,a,tree[root].mid) + Onenum((root<<1)+1,tree[root].mid,b); } } int Conenum(int root,int a,int b) { Down(root); if(a == tree[root].l && b == tree[root].r) { return tree[root].max1; } if(b <= tree[root].mid) return Conenum(root<<1,a,b); else if(tree[root].mid <= a) return Conenum((root<<1)+1,a,b); else { int m1,m2,res; m1 = Conenum(root<<1,a,tree[root].mid); m2 = Conenum((root<<1)+1,tree[root].mid,b); res = min(tree[root<<1].right1,tree[root].mid-a) + min(tree[(root<<1)+1].left1,b-tree[root].mid); return max(res,max(m1,m2)); } } int main() { int t,n,m,i,x,a,b; scanf("%d",&t); while (t--) { scanf("%d%d",&n,&m); for(i=0;i<n;i++) scanf("%d",&val[i]); Build(1,0,n); for(i=0;i<m;i++) { scanf("%d%d%d",&x,&a,&b); if(x<=2) Oper(1,a,b+1,x); else if(x==3) printf("%d/n",Onenum(1,a,b+1)); else printf("%d/n",Conenum(1,a,b+1)); } } return 0; }

你可能感兴趣的:(struct,String,tree,input,Build,output)