`
473687880
  • 浏览: 535907 次
文章分类
社区版块
存档分类
最新评论

hdu 3397 Sequence operation(很有意思的线段树题)

 
阅读更多

Sequence operation

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


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

Author
lxhgww&&shǎ崽

Source

Recommend
lcy
题意:
给你一个0,1数组。你可以对数组进行以下操作。
0 x y 把[x,y]之间的元素置为0。
1 x y 把[x,y]之间的元素置为1。
2 x y 把[x,y]之间的元素置为1变成0,0变成1。
3 x y 求[x,y]之间元素1的个数。
4 x y [x,y]之间最长连续1的长度。
思路:
对于0,1,3,4操作都很传统。区间更新区间统计。但是由于多了2操作所以就要多维护关于0的信息。这样进行2操作的时候之间交换1和0的信息就行了。还有查询的时候也有注意的地方。开始没注意那个地方导致wa数次。反复检查冗长的代码无数次。。。。可怜我的时间呀。。。哎。。。。。
详细见代码:
#include<algorithm>
#include<iostream>
#include<string.h>
#include<sstream>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100100;
int sta[maxn<<2],ml0[maxn<<2],mr0[maxn<<2],ml1[maxn<<2];//sta为标记。ml1为1左端连续。ml0为0左端连续
int mr1[maxn<<2],ma1[maxn<<2],ma0[maxn<<2],one[maxn<<2];//ma1为最大1连续数.one记录1的个数
void opp(int L,int R,int k)//对于2操作。0和1互换
{
    swap(ma0[k],ma1[k]);
    swap(ml0[k],ml1[k]);
    swap(mr0[k],mr1[k]);
    one[k]=R-L-one[k]+1;
}
void pushup(int L,int R,int k)//下传标记
{
    int ls,rs,mid;
    ls=k<<1;
    rs=ls|1;
    mid=(L+R)>>1;
    ml0[k]=ml0[ls];
    mr0[k]=mr0[rs];
    ml1[k]=ml1[ls];
    mr1[k]=mr1[rs];
    if(ml0[ls]==mid-L+1)
        ml0[k]+=ml0[rs];
    if(mr0[rs]==R-mid)
        mr0[k]+=mr0[ls];
    if(ml1[ls]==mid-L+1)
        ml1[k]+=ml1[rs];
    if(mr1[rs]==R-mid)
        mr1[k]+=mr1[ls];
    ma1[k]=max(ma1[ls],ma1[rs]);
    ma1[k]=max(ma1[k],mr1[ls]+ml1[rs]);
    ma0[k]=max(ma0[ls],ma0[rs]);
    ma0[k]=max(ma0[k],mr0[ls]+ml0[rs]);
    one[k]=one[ls]+one[rs];
}
void pushdown(int L,int R,int k)//上传
{
    int ls,rs,mid;
    ls=k<<1;
    rs=ls|1;
    mid=(L+R)>>1;
    //printf("mark %d->%d and %d->%d %d\n",L,mid,mid+1,R,sta[k]);
    if(sta[k]==0)
    {
        sta[ls]=sta[rs]=0;
        ma0[ls]=ml0[ls]=mr0[ls]=mid-L+1;
        ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=0;
        ma0[rs]=ml0[rs]=mr0[rs]=R-mid;

    }
    else if(sta[k]==1)
    {
        sta[ls]=sta[rs]=1;
        ma0[ls]=ml0[ls]=mr0[ls]=ma0[rs]=ml0[rs]=mr0[rs]=0;
        ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=mid-L+1;
        ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=R-mid;
    }
    else
    {
        if(sta[ls]!=-1)//2操作对于0,1标记直接0,1标记互换
        {
            if(sta[ls]==2)//原先有2直接变-1
                sta[ls]=-1;
            else
                sta[ls]^=1;
        }
        else
            sta[ls]=2;
        if(sta[rs]!=-1)
        {
            if(sta[rs]==2)
                sta[rs]=-1;
            else
                sta[rs]^=1;
        }
        else
            sta[rs]=2;
        opp(L,mid,ls);
        opp(mid+1,R,rs);
    }
    sta[k]=-1;
}
void btree(int L,int R,int k)
{
    int ls,rs,mid;
    sta[k]=-1;
    if(L==R)
    {
        scanf("%d",&one[k]);
        if(one[k])
        {
            ma1[k]=ml1[k]=mr1[k]=1;
            ma0[k]=ml0[k]=mr0[k]=0;
        }
        else
        {
             ma1[k]=ml1[k]=mr1[k]=0;
             ma0[k]=ml0[k]=mr0[k]=1;
        }
        return ;
    }
    ls=k<<1;
    rs=ls|1;
    mid=(L+R)>>1;
    btree(L,mid,ls);
    btree(mid+1,R,rs);
    pushup(L,R,k);
    //printf("%d->%d\n",L,R);
    //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);
}
void update(int L,int R,int l,int r,int k,int op)
{
    int ls,rs,mid;
    if(l==L&&r==R)
    {
        if(op==0)
        {
            sta[k]=0;
            ma0[k]=ml0[k]=mr0[k]=R-L+1;
            ma1[k]=ml1[k]=mr1[k]=one[k]=0;
        }
        else if(op==1)
        {
            sta[k]=1;
            ma0[k]=ml0[k]=mr0[k]=0;
            ma1[k]=ml1[k]=mr1[k]=one[k]=R-L+1;
        }
        else
        {
            if(sta[k]==-1)
                sta[k]=2;
            else if(sta[k]==2)
                sta[k]=-1;
            else
                sta[k]^=1;
            opp(L,R,k);
        }
        //printf("mark %d->%d %d\n",L,R,op);
        //printf("%d->%d\n",L,R);
        //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);
        return ;
    }
    if(sta[k]!=-1)
        pushdown(L,R,k);
    ls=k<<1;
    rs=ls|1;
    mid=(L+R)>>1;
    if(l>mid)
        update(mid+1,R,l,r,rs,op);
    else if(r<=mid)
        update(L,mid,l,r,ls,op);
    else
    {
        update(L,mid,l,mid,ls,op);
        update(mid+1,R,mid+1,r,rs,op);
    }
    pushup(L,R,k);
    //printf("%d->%d\n",L,R);
    //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);
}
int qu(int L,int R,int l,int r,int k,int op)
{
    int ls,rs,mid,tmp,ll,rr;
    if(sta[k]==0)
        return 0;
    if(sta[k]==1)
        return r-l+1;
    if(l==L&&r==R)
    {
        if(op==3)
            return one[k];
        else
            return ma1[k];
    }
    if(sta[k]!=-1)
        pushdown(L,R,k);
    ls=k<<1;
    rs=ls|1;
    mid=(L+R)>>1;
    if(l>mid)
        return qu(mid+1,R,l,r,rs,op);
    else if(r<=mid)
        return qu(L,mid,l,r,ls,op);
    else
    {
        if(op==3)
            return qu(L,mid,l,mid,ls,op)+qu(mid+1,R,mid+1,r,rs,op);
        else//4对于分离操作尤其注意!!最大值只能是以下几种情况。
        {
            tmp=max(qu(L,mid,l,mid,ls,op),qu(mid+1,R,mid+1,r,rs,op));//最大值在左儿子或右儿子中
            ll=max(mid-mr1[ls]+1,l);//最大值在中间区域
            rr=min(mid+ml1[rs],r);//注意范围
            tmp=max(tmp,rr-ll+1);
            return tmp;
        }
    }

}
int main()
{
    int t,n,m,op,a,b;

    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        btree(1,n,1);
        while(m--)
        {
            scanf("%d%d%d",&op,&a,&b);
            a++,b++;
            if(op<3)
                update(1,n,a,b,1,op);
            else
                printf("%d\n",qu(1,n,a,b,1,op));
        }
    }
    return 0;
}


分享到:
评论

相关推荐

    ACM hdu 线段树题目+源代码

    ACM hdu 线段树题目+源代码 线段树是一种非常重要的数据结构,它广泛应用于算法竞赛和实际编程中。今天,我们将通过 ACM hdu 的几个题目来学习和掌握线段树的基本概念和应用。 线段树的基本概念 线段树是一种...

    hdu acm1166线段树

    hdu 1166线段树代码

    hdu 1166线段树

    标题与描述均提到了“hdu 1166线段树”,这表明文章的核心是关于线段树在解决特定问题中的应用。线段树是一种数据结构,主要用于处理区间查询和更新操作,尤其是在大规模数据集上。在本例中,通过分析给定的部分代码...

    线段树完整版

    ### 线段树知识点详解 #### 一、线段树基本概念与应用 线段树是一种二叉树数据结构,常用于处理区间查询或区间更新的问题。它将一个线性序列分割成多个不连续的段,每一个节点代表一个区间,并且通过递归的方式将...

    【hdu5306】Gorgeous Sequence 线段树区间最值操作-附件资源

    【hdu5306】Gorgeous Sequence 线段树区间最值操作-附件资源

    线段树入门学习(兼解HDU1754)

    线段树可以很好地解决这类问题,通过一次预处理构建线段树,后续的修改和查询操作都能在较短的时间复杂度内完成,比直接遍历数组的方法高效得多。 在“Main.java”文件中,我们可以预期看到线段树的实现代码。代码...

    线段树题目

    - **HDU 3397**:这道题需要设计两个标记来处理异或和覆盖之间的关系。在实现时需要注意不同标记的传递顺序可能会导致不同的结果。 - **FZU 1608**:涉及到更新后的区间长度查询问题。关键在于如何正确地更新和传递...

    HH神总结的线段树专辑-超经典的

    通过以上分析可以看出,线段树作为一种高效的数据结构,在处理区间相关问题时具有很强的实用性。同时,随着作者经验的增长和技术的进步,线段树的实现也变得越来越简洁和优雅。希望通过对这些经典题目的分析和总结,...

    NumberSequence

    在IT行业中,"Number Sequence"通常指的是在特定系统或应用中用于生成自动递增或递减的数字序列。这些序列可以用于唯一标识记录、订单号、发票号等,确保数据的唯一性和可追踪性。在Microsoft Dynamics AX(现称为...

    线段树入门

    线段树入门资料,有利于初学者学习,让他们详细了解线段树。

    hdu.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj

    【标题】"hdu.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj" 提供的信息是关于一个压缩文件,其中包含了一个名为 "HDU 1089.cpp" 的源代码文件,这个文件是为了解决杭州电子科技大学(Hangzhou Dianzi ...

    hdu 3333 turing tree 解题报告

    **线段树(Segment Tree)**是一种用于处理区间查询和修改的高效数据结构。在这个问题中,线段树的每个节点存储的信息不仅仅是区间内的和,而是区间内不同数字的和。线段树的每个节点包含以下信息: 1. `a` 和 `b`...

    ACM HDU题目分类

    搜索题是 ACM HDU 题目分类中的一大类,例如,1010 搜索题,剪枝很关键;1016 经典的搜索;1026 搜索;1043 经典搜索题,八数码问题;1044 稍微有点麻烦的搜索题;1045 搜索题,可用匹配做 等等。 贪心算法 贪心...

    hdu.rar_hdu

    "hdu.rar_hdu"这个压缩包文件很可能是某位程序员整理的他在HDU上解决过的题目代码集合。这些代码通常包含了对各种算法的应用,例如排序、搜索、图论、动态规划等,对于学习算法和准备编程竞赛的初学者来说是一份宝贵...

    hdu 300+ AC 代码

    2. **线段树**:线段树是一种数据结构,用于高效地处理区间查询和更新操作。它可以实时维护一个区间内的信息,如求和、最大值或最小值。线段树在处理动态区间问题时非常有效,如在数组上进行区间加法、区间求和等...

    离线OJ题库(HDU ZJU等,部分有答案)

    离线OJ题库是为编程爱好者和程序员提供的一种便捷的学习资源,主要包含来自不同在线判题系统(如HDU - 浙江大学多模式在线评测系统,ZJU - 浙江大学在线评测系统等)的编程题目。这类题库通常包含多种编程语言的题目...

    【题解】「HDU1166」敌兵布阵(线段树)

    题面 【题目描述】 有nnn个营地,已知每个营地的人数,有四条命令: (1)Add(1) Add(1)Add iii jjj,iii和jjj为正整数,表示第iii个营地增加jjj个人(jjj不超过303030) (2)Sub(2)Sub(2)Sub iii jjj ,iii和jjj为正...

    HDU_2010.rar_hdu 2010_hdu 20_hdu acm20

    "hdu"可能是指杭州电子科技大学(Hangzhou Dianzi University),这所学校经常举办ACM编程竞赛,并有自己的在线判题系统——HDU Online Judge,供参赛者提交代码并测试解决方案。 【压缩包子文件的文件名称列表】中...

    杭电HDU2050题的ac程序

    一个十分简单的程序,能够ac杭电hdu的第2050题,无注释,简单明了

Global site tag (gtag.js) - Google Analytics