HDU-3397 线段树+区间合并

来源:互联网 发布:基于php视频网站设计 编辑:程序博客网 时间:2024/05/16 05:36

Sequence operation


                                                                   Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                                            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]
 

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
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
原创粉丝点击