线段树 HDU 3397(真)

Posted HelloWorld!--By-MJY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树 HDU 3397(真)相关的知识,希望对你有一定的参考价值。

5 种操作  0 1 然后 异或 似乎这种2个更新的先后每次都搞不清

覆盖有覆盖就可以不异或

也不知道为什么

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define MAXN   100010

struct node
{
    int l,r,ls,rs,ms; // 左边连续的1  右边  最多
    int lz,rz,mz;     //         0
    int XOR,cov;      // 异或  lazy
    int sum;          //和
}x[MAXN<<3];
int z[MAXN];
void makexor(int a)//0 1 交换
{
    swap(x[a].ls,x[a].lz);
    swap(x[a].rs,x[a].rz);
    swap(x[a].ms,x[a].mz);
    x[a].sum=x[a].r-x[a].l+1-x[a].sum;
}
void push_up(int a)
{
    int len=x[a].r-x[a].l+1;
    x[a].ls=x[a<<1].ls;
    x[a].rs=x[a<<1|1].rs;
    x[a].ms=max(x[a<<1].ms,x[a<<1|1].ms);
    if(x[a].ls==(len+1)>>1)  //这边就是普通的区间合并
        x[a].ls+=x[a<<1|1].ls;
    if(x[a].rs==len>>1)
        x[a].rs+=x[a<<1].rs;
    int mid=(x[a].r+x[a].l)>>1;
//    if(z[mid]==z[mid+1]&&z[mid]==1)        //一开始这里一直错  其实后面更新了  不用考虑这个
        x[a].ms=max(x[a].ms,x[a<<1].rs+x[a<<1|1].ls);

    x[a].lz=x[a<<1].lz;
    x[a].rz=x[a<<1|1].rz;
    x[a].mz=max(x[a<<1].mz,x[a<<1|1].mz);
    if(x[a].lz==(len+1)>>1)
        x[a].lz+=x[a<<1|1].lz;
    if(x[a].rz==len>>1)
        x[a].rz+=x[a<<1].rz;
        x[a].mz=max(x[a].mz,x[a<<1].rz+x[a<<1|1].lz);

    x[a].sum=x[a<<1].sum+x[a<<1|1].sum;
}
void push_down(int a)
{
    if(x[a].cov!=-1)
    {
        int l=x[a].l;
        int r=x[a].r;
        int len=r-l+1;
        x[a<<1].cov=x[a<<1|1].cov=x[a].cov;
        x[a<<1].XOR=x[a<<1|1].XOR=0;

        x[a<<1].ls=x[a<<1].rs=x[a<<1].ms=x[a].cov?(len+1)>>1:0;
        x[a<<1].lz=x[a<<1].rz=x[a<<1].mz=x[a].cov?0:(len+1)>>1;
        x[a<<1].sum=x[a].cov?(len+1)>>1:0;

        x[a<<1|1].ls=x[a<<1|1].rs=x[a<<1|1].ms=x[a].cov?len>>1:0;
        x[a<<1|1].lz=x[a<<1|1].rz=x[a<<1|1].mz=x[a].cov?0:len>>1;
        x[a<<1|1].sum=x[a].cov?len>>1:0;

        x[a].cov=-1;
    }
    if(x[a].XOR)
    {
        x[a].XOR=0;
        x[a<<1].XOR^=1;
        x[a<<1|1].XOR^=1;
        makexor(a<<1);
        makexor(a<<1|1);
    }
}

void Build(int l,int r,int a)
{
    x[a].l=l;
    x[a].r=r;
    x[a].XOR=0;
    x[a].cov=-1;
    if(l==r)
    {
        x[a].ls=x[a].rs=x[a].ms=(z[l]==1);
        x[a].lz=x[a].rz=x[a].mz=(z[l]==0);
        x[a].sum=z[l];
        x[a].cov=z[l];
        return ;
    }
    int mid=(l+r)>>1;
    Build(l,mid,a<<1);
    Build(mid+1,r,a<<1|1);
    push_up(a);
}
void update(int l,int r,int a1,int b1,int w,int a)
{
    push_down(a);
    if(a1<=l&&r<=b1)
    {
        if(w<2)
        {
            int len=r-l+1;
            x[a].cov=w;
            x[a].ls=x[a].rs=x[a].ms=w?len:0;
            x[a].lz=x[a].rz=x[a].mz=w?0:len;
            x[a].sum=w?len:0;
            x[a].XOR=0;
        }
        else
        {
            x[a].XOR=1;
            makexor(a);
        }
        return ;
    }
    int mid=(l+r)>>1;
    if(a1<=mid)
        update(l,mid,a1,b1,w,a<<1);
    if(b1>mid)
        update(mid+1,r,a1,b1,w,a<<1|1);
    push_up(a);
}
int query_sum(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) {
        return x[rt].sum;
    }
    push_down(rt);
    int m=(l+r)>>1;
    int ans=0;
    if(L<=m)
        ans+=query_sum(L,R,l,m,rt<<1);
    if(m<R)
        ans+=query_sum(L,R,m+1,r,rt<<1|1);
    return ans;
}
int query_len(int L,int R,int l,int r,int rt)
{
    push_down(rt);
    if(L<=l&&r<=R) {
        return x[rt].ms;
    }

    int m=(l+r)>>1;
    int ans=0;
    if(L<=m)
        ans=max(ans,query_len(L,R,l,m,rt<<1));
    if(m<R)
        ans=max(ans,query_len(L,R,m+1,r,rt<<1|1));
    return max(ans,min(m-L+1,x[rt<<1].rs)+min(R-m,x[rt<<1|1].ls));
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&z[i]);
        Build(1,n,1);

        while(m--)
        {
            int op,a,b;
            scanf("%d%d%d",&op,&a,&b);
            a++;
            b++;
            if(op<=2)
                update(1,n,a,b,op,1);
            else   if(op==3)
                printf("%d\n",query_sum(a,b,1,n,1));
            else
                printf("%d\n",query_len(a,b,1,n,1));
        }
    }
    return 0;
}

 

以上是关于线段树 HDU 3397(真)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3397 线段树区间修改

hdu-3397 Sequence operation 线段树多种标记

hdu 3397 Sequence operation (线段树 区间合并 多重标记)

HDU 3397 Sequence operation 多标记线段树

hdu 3397 Sequence operation 线段树 区间更新 区间合并

HDU 5692 线段树