hdu 3397 Sequence operation

题目大意:

三个操作  两个查询

Change operations:
0 a b change all characters into '0's in [a , b]     区间全部变 0
1 a b change all characters into '1's in [a , b]     区间全部变 1
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]   1变0   0变1
Output operations:
3 a b output the number of '1's in [a, b]           输出多少个1
4 a b output the length of the longest continuous '1' string in [a , b] 输出最长连续1


哭死了。。找了几个小时的BUG。。。结果是build 的 有一个变量名写错了   让一个变量没有赋值。。。


思路:

难点就在 2 操作上   对区间信息的维护上。  因为会1-0转换。所以要输出1 的信息的时候  还要记住0的信息  

这样在转换的时候  就可以直接交换他们的信息就可以了。

然后用cov 标记   标记的方式 在代码上也注释出来了

然后输出需要输出最长连续的1   所以我们就要记录  最长1的   这一点我给个傻仔的链接。里面所说的POJ 3667  HOTEL 很像    


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
#define maxn 100005
using namespace std;

int tre[maxn<<2];//区间最长1 
int dan[maxn<<2];//区间最长0
int cnt[maxn<<2];//区间里1 的数量
int lemzer[maxn<<2];//区间左端点开始  最长连续的  0
int rimzer[maxn<<2];//----右----------------------0
int lemone[maxn<<2];//----左----------------------1
int rimone[maxn<<2];//----右----------------------1
int cov[maxn<<2];//-1未更新  0全是0  1有反转操作   2全是1
int n,m;

inline void Turn(int num,int len)//2操作的反转
{
    swap(lemzer[num],lemone[num]);
    swap(rimzer[num],rimone[num]);
    swap(dan[num],tre[num]);
    cnt[num]=len-cnt[num];
}
inline void pushup(int num,int s,int e)//这个和上面所说的hotel里的是一个概念
{
    int mid=(s+e)>>1;
    lemzer[num]=lemzer[num<<1];
    lemone[num]=lemone[num<<1];
    rimzer[num]=rimzer[num<<1|1];
    rimone[num]=rimone[num<<1|1];

    if(lemzer[num]==mid-s+1)lemzer[num]+=lemzer[num<<1|1];
    if(rimzer[num]==e-mid)rimzer[num]+=rimzer[num<<1];
    if(lemone[num]==mid-s+1)lemone[num]+=lemone[num<<1|1];
    if(rimone[num]==e-mid)rimone[num]+=rimone[num<<1];

    tre[num] = max(rimone[num<<1]+lemone[num<<1|1],max(tre[num<<1],tre[num<<1|1]));
    dan[num] = max(rimzer[num<<1]+lemzer[num<<1|1],max(dan[num<<1],dan[num<<1|1]));
    cnt[num] = cnt[num<<1]+cnt[num<<1|1];
}
void pushdown(int num,int s,int e)
{
    if(cov[num]!=-1)
    {
        int mid=(s+e)>>1;
        if(cov[num]==1)//这里要注意的就是  当这个区间存在反转操作的时候  下推的话  如果下个区间cov是0  就要变2  2 就要变0
        {
            if(cov[num<<1]!=0 && cov[num<<1]!=2)
            cov[num<<1]=-cov[num<<1];
            else
            {
                if(cov[num<<1]==0)cov[num<<1]=2;
                else if(cov[num<<1]==2)cov[num<<1]=0;
            }
            Turn(num<<1,mid-s+1);

            if(cov[num<<1|1]!=0 && cov[num<<1|1]!=2)
            cov[num<<1|1]=-cov[num<<1|1];
            else
            {
                if(cov[num<<1|1]==0)cov[num<<1|1]=2;
                else if(cov[num<<1|1]==2)cov[num<<1|1]=0;
            }
            Turn(num<<1|1,e-mid);
        }
        else
        {
            cov[num<<1]=cov[num<<1|1]=cov[num];
            cnt[num<<1]=tre[num<<1]=lemone[num<<1]=rimone[num<<1]=cov[num]==2?mid-s+1:0;
            dan[num<<1]=lemzer[num<<1]=rimzer[num<<1]=cov[num]==2?0:mid-s+1;
            cnt[num<<1|1]=tre[num<<1|1]=lemone[num<<1|1]=rimone[num<<1|1]=cov[num]==2?e-mid:0;
            dan[num<<1|1]=lemzer[num<<1|1]=rimzer[num<<1|1]=cov[num]==2?0:e-mid;
        }
        cov[num]=-1;
    }
}

void build(int num,int s,int e)
{
    cov[num]=-1;
    if(s==e)
    {
        int a;
        scanf("%d",&a);
        if(a==1)
        {
            cnt[num]=tre[num]=lemone[num]=rimone[num]=1;
            dan[num]=lemzer[num]=rimzer[num]=0;//就是。。。错在。。这里。。。写成了两个 lemzer。。。头疼的变量名
            cov[num]=2;
        }
        else
        {
            cnt[num]=tre[num]=lemone[num]=rimone[num]=0;
            dan[num]=lemzer[num]=rimzer[num]=1;
            cov[num]=0;
        }
        return;
    }
    int mid=(s+e)>>1;

    build(lson);
    build(rson);
    pushup(num,s,e);
}

void update(int num,int s,int e,int l,int r,int op)
{
    if(l<=s && r>=e)
    {
        if(op==0)
        {
            lemzer[num]=rimzer[num]=dan[num]=e-s+1;
            lemone[num]=rimone[num]=tre[num]=0;
            cnt[num]=0;
            cov[num]=0;
        }
        else if(op==1)
        {
            lemzer[num]=rimzer[num]=dan[num]=0;
            lemone[num]=rimone[num]=tre[num]=e-s+1;
            cnt[num]=e-s+1;
            cov[num]=2;
        }
        else
        {
            if(cov[num]==2)cov[num]=0;//这里也要注意。。
            else if(cov[num]==0)cov[num]=2;
            else cov[num]=-cov[num];

            Turn(num,e-s+1);
        }
        return;
    }
    int mid=(s+e)>>1;
    pushdown(num,s,e);
    if(l<=mid)update(lson,l,r,op);
    if(r>mid)update(rson,l,r,op);
    pushup(num,s,e);
}
int query(int num,int s,int e,int l,int r,int op)
{
    if(l<=s && r>=e)
    {
        if(op==3)return cnt[num];
        else return tre[num];
        
    }
    int mid=(s+e)>>1;
    pushdown(num,s,e);
    if(op==3)
    {
        if(r<=mid)return query(lson,l,r,op);
        else if(l>mid)return query(rson,l,r,op);
        else return query(lson,l,mid,op)+query(rson,mid+1,r,op);
    }
    else
    {
        if(r<=mid)return query(lson,l,r,op);
        else if(l>mid)return query(rson,l,r,op);
        else
        {
            int tmp=min(mid-l+1,rimone[num<<1])+min(r-mid,lemone[num<<1|1]);//这里是我没想到的。。大家自己斟酌一下。。
            return max(tmp,max(query(lson,l,mid,op),query(rson,mid+1,r,op)));
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        while(m--)
        {
            int a,b,c;

            scanf("%d%d%d",&a,&b,&c);
            b++;
            c++;

            if(a<=2)
            update(1,1,n,b,c,a);
            else
            printf("%d\n",query(1,1,n,b,c,a));
        }
    }
    return 0;
}

/*
1
10 1000
1 1 1 1 1 0 1 1 1 1
2 2 3
2 3 5
2 5 8

*/


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值