HDU3397 Sequence operation

题意:给出几个操作。。。0 更新一段区间内的值全为0.

1跟新一段区间内全为1.

2一段区间内的值全部异或起来

3查询这段区间内1的个数。

4查询这段区间内连续1的个数。。。

这题简直操蛋。。。WA了20+次。。。

其实原理很简单,只要注意下异或覆盖和直接覆盖的先后顺序就可以,如果先异或后直接覆盖,则异或覆盖不存在了,反过来,异或覆盖是存在了。。。

一直以为是顺序出了问题。。队友一看。。。查询写错了,查询连续时。。居然直接无脑相加了。。。。

/*************************************************************************
    > File Name: 3397.cpp
    > Author: tjw
    > Mail:
    > Created Time: 2014年11月04日 星期二 15时35分30秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define lll (long long)
#define ls (k<<1)
#define rs (k<<1|1)
using namespace std;
const int MAXN=100010;
struct TREE
{
    int l,r;
    int mark,markxor;
    int msum0,lsum0,rsum0;
    int msum1,lsum1,rsum1;
    int mmax0,mmax1;
    int mid()
    {
        return (l+r)>>1;
    }
}tree[MAXN<<2];
int num;
void pushup(int k,int m)
{
    tree[k].mmax1=tree[k<<1].mmax1+tree[k<<1|1].mmax1;
    tree[k].lsum1=tree[k<<1].lsum1;
    if(tree[k<<1].lsum1==m-(m>>1))
        tree[k].lsum1+=tree[k<<1|1].lsum1;
    tree[k].rsum1=tree[k<<1|1].rsum1;
    if(tree[k<<1|1].rsum1==(m>>1))
        tree[k].rsum1+=tree[k<<1].rsum1;
    tree[k].msum1=max(tree[k<<1].msum1,tree[k<<1|1].msum1);
    tree[k].msum1=max(tree[k].msum1,tree[k<<1].rsum1+tree[k<<1|1].lsum1);
    tree[k].mmax0=tree[k<<1].mmax0+tree[k<<1|1].mmax0;
    tree[k].lsum0=tree[k<<1].lsum0;
    if(tree[k<<1].lsum0==m-(m>>1))
        tree[k].lsum0+=tree[k<<1|1].lsum0;
    tree[k].rsum0=tree[k<<1|1].rsum0;
    if(tree[k<<1|1].rsum0==(m>>1))
        tree[k].rsum0+=tree[k<<1].rsum0;
   tree[k].msum0=max(tree[k<<1].msum0,tree[k<<1|1].msum0);
    tree[k].msum0=max(tree[k].msum0,tree[k<<1].rsum0+tree[k<<1|1].lsum0);
    return;
}
void init(int rt,int m,int cmd){
   tree[rt].lsum0=tree[rt].rsum0=tree[rt].msum0=tree[rt].mmax0=m*(1-cmd);
   tree[rt].lsum1=tree[rt].rsum1=tree[rt].msum1=tree[rt].mmax1=m*cmd;
}
void change(int k){
    swap(tree[k].lsum0,tree[k].lsum1);
    swap(tree[k].rsum0,tree[k].rsum1);
    swap(tree[k].msum0,tree[k].msum1);
    swap(tree[k].mmax0,tree[k].mmax1);
}
void pushdown(int k,int m)
{
    if(tree[k].mark!=-1)
    {
        tree[k<<1].mark=tree[k<<1|1].mark=tree[k].mark;
        tree[k<<1].markxor=tree[k<<1|1].markxor=0;
        init(k<<1,m-(m>>1),tree[k].mark);
        init(k<<1|1,(m>>1),tree[k].mark);
        tree[k].mark=-1;
    }
    else if(tree[k].markxor)
    {
        if(tree[k<<1].mark!=-1)
        {
            tree[k<<1].mark^=1;
            init(k<<1,m-(m>>1),tree[k<<1].mark);
        }
        else
        {
            tree[k<<1].markxor^=1;
            change(k<<1);
        }
        if(tree[k<<1|1].mark!=-1)
        {
            tree[k<<1|1].mark^=1;
            init(k<<1|1,(m>>1),tree[k<<1|1].mark);
        }
        else
        {
            tree[k<<1|1].markxor^=1;
            change(k<<1|1);
        }
        tree[k].markxor=0;
    }
}
void build(int l,int r,int k)
{
    tree[k].l=l;
    tree[k].r=r;
    tree[k].mark=-1;
    tree[k].markxor=0;
    if(l==r)
    {
        scanf("%d",&num);
        tree[k].msum0=tree[k].lsum0=tree[k].rsum0=tree[k].mmax0=(num?0:1);
        tree[k].msum1=tree[k].lsum1=tree[k].rsum1=tree[k].mmax1=(num?1:0);
        return ;
    }
    int mid=tree[k].mid();
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    pushup(k,tree[k].r-tree[k].l+1);
}
void update(int l,int r,int op,int k)
{
    if(tree[k].l>=l&&tree[k].r<=r)
    {
        if(op==2)
        {
            if(tree[k].mark!=-1)
            {
                tree[k].mark^=1;
                init(k,tree[k].r-tree[k].l+1,tree[k].mark);
            }
            else
            {
                tree[k].markxor^=1;
                change(k);
            }
            return;
        }
        tree[k].mark=op;
        tree[k].markxor=0;
        init(k,tree[k].r-tree[k].l+1,op);
        return;
    }
    pushdown(k,tree[k].r-tree[k].l+1);
    int mid=tree[k].mid();
    if(r<=mid)
        update(l,r,op,k<<1);
    else if(l>mid)
        update(l,r,op,k<<1|1);
    else
    {
        update(l,mid,op,k<<1);
        update(mid+1,r,op,k<<1|1);
    }
    pushup(k,tree[k].r-tree[k].l+1);
}
int query1(int l,int r,int k)
{
    if(tree[k].l>=l&&tree[k].r<=r)
    {
        return tree[k].mmax1;
    }
    pushdown(k,tree[k].r-tree[k].l+1);
    int mid=tree[k].mid();
    if(r<=mid)
        return query1(l,r,k<<1);
    else if(l>mid)
        return query1(l,r,k<<1|1);
    else
    {
        int t1=query1(l,mid,k<<1);
        int t2=query1(mid+1,r,k<<1|1);
        return t1+t2;
    }
}
int query2(int l,int r,int k)
{
    if(tree[k].l>=l&&tree[k].r<=r)
    {
        return tree[k].msum1;
    }
    pushdown(k,tree[k].r-tree[k].l+1);
    int mid=tree[k].mid();
    if(r<=mid)
        return query2(l,r,k<<1);
    else if(l>mid)
        return query2(l,r,k<<1|1);
    else
    {
        int t1=query2(l,mid,k<<1);
        int t2=query2(mid+1,r,k<<1|1);
        int ans1=max(t1,t2);
        int ans2=min(mid-l+1,tree[k<<1].rsum1)+min(r-mid,tree[k<<1|1].lsum1);
        return max(ans1,ans2);
    }
}
int main()
{
    int t,n,m,i;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(0,n-1,1);
        while(m--)
        {
            int a,b,op;
            scanf("%d%d%d",&op,&a,&b);
            if(op>2)
            {
                if(op==3)
                {
                    printf("%d\n",query1(a,b,1));
                }
                else
                    printf("%d\n",query2(a,b,1));
            }
            else
            {
                update(a,b,op,1);
            }
        }
    }
    return 0;
}
/*
5
5 4
0 0 0 0 0
1 0 4
2 0 4
3 1 2
4 1 2
5 4
0 0 0 0 0
2 0 4
1 0 4
3 1 2
4 1 2
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值