HDU-3397 线段树+区间合并
来源:互联网 发布:基于php视频网站设计 编辑:程序博客网 时间:2024/05/16 05:36
Sequence operation
Total Submission(s): 8068 Accepted Submission(s): 2416
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]
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.
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
110 100 0 0 1 1 0 1 0 1 11 0 23 0 52 2 24 0 40 3 62 3 74 2 81 0 50 5 63 3 9
Sample Output
5265
Author
lxhgww&&shǎ崽
Source
HDOJ Monthly Contest – 2010.05.01
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3397
总结:
好久没写线段树,最近想复习一下,就找了这道以前觉得最复杂的区间合并来练手,上次做这道题还是一年半之前的8月集训,翻翻当时HDU上的记录,这道题整整调了3天。当时对pushdown和pushup这两个操作的理解还没有到位,两种标记处理的很拙劣。现在写线段树的境界有所提高,拿出来重新做,结果还是WA了4遍才过,所以写下这篇博客,记录一下这次错的几个地方:
(1)第一个,翻转操作标记只是置1,忘记了偶数次翻转的抵消;
(2)第二个,手残,区间合并的一个右边区间的左边连续1个数llb打成rrb,比赛的话写完代码一定要仔细查一遍;
(3)第三个,区间合并是有条件的,忽略了mid必须在[a,b]之间的判断;
(4)第四个,一个操作参数2打成3,原因是这题操作标签是0~4,印象中成了1~5,检查代码各种感觉不会错的细小的地方也要想一下!
AC代码:
最后附上这次写的姿势比较优美的代码:
import java.io.*;public class Main { static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); static int nextInt() throws IOException { in.nextToken(); return (int)in.nval; } static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out)); static int T,n,m,a,b,op,maxn=100000; static int[] aa=new int[maxn]; static int[] ss=new int[maxn<<2]; static int[] lz=new int[maxn<<2]; static int[] re=new int[maxn<<2]; static int[] lla=new int[maxn<<2]; static int[] rra=new int[maxn<<2]; static int[] mma=new int[maxn<<2]; static int[] llb=new int[maxn<<2]; static int[] rrb=new int[maxn<<2]; static int[] mmb=new int[maxn<<2]; static void pushup(int k,int l,int r) { int mid=(l+r)/2; ss[k]=ss[k*2+1]+ss[k*2+2]; lla[k]=lla[k*2+1]+(lla[k*2+1]==mid+1-l?lla[k*2+2]:0); rra[k]=rra[k*2+2]+(rra[k*2+2]==r-mid?rra[k*2+1]:0); mma[k]=Math.max(rra[k*2+1]+lla[k*2+2],Math.max(mma[k*2+1],mma[k*2+2])); llb[k]=llb[k*2+1]+(llb[k*2+1]==mid+1-l?llb[k*2+2]:0); rrb[k]=rrb[k*2+2]+(rrb[k*2+2]==r-mid?rrb[k*2+1]:0); mmb[k]=Math.max(rrb[k*2+1]+llb[k*2+2],Math.max(mmb[k*2+1],mmb[k*2+2])); } static void pushdown(int k,int l,int r) { int mid=(l+r)/2; if(lz[k]!=-1) { up(l,r,k*2+1,l,mid,lz[k]); up(l,r,k*2+2,mid+1,r,lz[k]); } if(re[k]==1) { up(l,r,k*2+1,l,mid,2); up(l,r,k*2+2,mid+1,r,2); } lz[k]=-1;re[k]=0; } static void build(int k,int l,int r) { lz[k]=-1;re[k]=0; if(l==r) { lla[k]=rra[k]=mma[k]=1-aa[l]; llb[k]=rrb[k]=mmb[k]=ss[k]=aa[l]; return; } int mid=(l+r)/2; build(k*2+1,l,mid); build(k*2+2,mid+1,r); pushup(k,l,r); } static void up(int a,int b,int k,int l,int r,int op) { if(a>r||b<l) return; if(a<=l&&r<=b) { if(op==2) { ss[k]=r-l+1-ss[k]; re[k]=(re[k]+1)%2; int c; c=lla[k];lla[k]=llb[k];llb[k]=c; c=rra[k];rra[k]=rrb[k];rrb[k]=c; c=mma[k];mma[k]=mmb[k];mmb[k]=c; } else { lz[k]=op;re[k]=0; int x=op==0?0:r-l+1; ss[k]=llb[k]=rrb[k]=mmb[k]=x; lla[k]=rra[k]=mma[k]=r-l+1-x; } } else { int mid=(l+r)/2; pushdown(k,l,r); up(a,b,k*2+1,l,mid,op); up(a,b,k*2+2,mid+1,r,op); pushup(k,l,r); } } static int sum(int a,int b,int k,int l,int r) { if(a>r||b<l) return 0; if(a<=l&&r<=b) return ss[k]; int mid=(l+r)/2; pushdown(k,l,r); return sum(a,b,k*2+1,l,mid)+sum(a,b,k*2+2,mid+1,r); } static int len(int a,int b,int k,int l,int r) { if(a>r||b<l) return 0; if(a<=l&&r<=b) return mmb[k]; int mid=(l+r)/2,res=0; pushdown(k,l,r); if(a<=mid&&mid<b) { res+=Math.min(mid+1-a,rrb[k*2+1]); res+=Math.min(b-mid,llb[k*2+2]); } res=Math.max(res,len(a,b,k*2+1,l,mid)); res=Math.max(res,len(a,b,k*2+2,mid+1,r)); return res; } public static void main(String[] args) throws IOException { T=nextInt(); while(T-->0) { n=nextInt();m=nextInt(); for(int i=0;i<n;i++) aa[i]=nextInt(); build(0,0,n-1); while(m-->0) { op=nextInt(); a=nextInt();b=nextInt(); if(op==3) out.println(sum(a,b,0,0,n-1)); else if(op==4) out.println(len(a,b,0,0,n-1)); else up(a,b,0,0,n-1,op); } out.flush(); } }}
0 0
- hdu 3397(线段树区间合并)
- HDU 3397 线段树区间合并
- HDU-3397 线段树+区间合并
- hdu 3397 Sequence operation(线段树区间覆盖,区间合并)
- HDU 3397 Sequence operation 线段树(区间合并)
- hdu 3397 线段树+区间合并+懒惰标记 好题
- hdu 3397 Sequence operation(线段树,lazy,区间合并)
- 【线段树】HDU 3397 Sequence operation 区间合并
- HDU 3397 Sequence operation (线段树区间合并入门)
- HDU 3397 Sequence operation(线段树区间合并)
- HDU 3397 - Sequence operation(线段树+区间合并)
- HDU 3397 Sequence operation(线段树的区间合并)
- HDU 3308 线段树+区间合并
- hdu 3308 LCIS 线段树 区间合并
- hdu 3308LCIS 线段树 区间合并
- [HDU 3308]LCIS[线段树][区间合并]
- hdu 3308 线段树区间合并
- hdu 3308 线段树区间合并
- jQuery AJAX详解
- composer问题汇总
- LeetCode 41. First Missing Positive
- 回文数
- Java内存泄露原因详解
- HDU-3397 线段树+区间合并
- Android之内容提供者,你确定不进来看一看???
- ContentProvider实现增删查改
- 跟天齐老师学Spark(7)--关于Spark的RDD
- 1002. A+B for Polynomials (25)
- 新手如何将less文件转换成css文件
- json介绍与解析
- js check all checkbox
- Kruskal算法的C语言程序