习题日常第二十五练

1序列操作(题目链接

这个题是线段树的基础综合运用题。对于细节要求特别高,需要对每一个标记以及互相之间的关系相当清晰。大体的思路就是连续的0或者1只可能出现在左面或者最右面或者序列中间,用线段是进行维护即可。具体见代码。

#include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
#define ll long long int
const int mod=10007;
using namespace std;
struct node
{
    int l,r,lmax1,rmax1,sum1,sum0,lmax0,rmax0,lian1,lian0,tag,tagev;
}t[400010];
int a[100010];
void pushdown(int ri)
{
    t[ri].sum0=t[ri<<1].sum0+t[ri<<1|1].sum0;
    t[ri].sum1=t[ri<<1].sum1+t[ri<<1|1].sum1;
    t[ri].lmax0=(t[ri<<1].lmax0==t[ri<<1].r-t[ri<<1].l+1?t[ri<<1].lmax0+t[ri<<1|1].lmax0:t[ri<<1].lmax0);
    t[ri].rmax0=(t[ri<<1|1].rmax0==t[ri<<1|1].r-t[ri<<1|1].l+1?t[ri<<1|1].rmax0+t[ri<<1].rmax0:t[ri<<1|1].rmax0);
    t[ri].lmax1=(t[ri<<1].lmax1==t[ri<<1].r-t[ri<<1].l+1?t[ri<<1].lmax1+t[ri<<1|1].lmax1:t[ri<<1].lmax1);
    t[ri].rmax1=(t[ri<<1|1].rmax1==t[ri<<1|1].r-t[ri<<1|1].l+1?t[ri<<1|1].rmax1+t[ri<<1].rmax1:t[ri<<1|1].rmax1);
    t[ri].lian0=max(t[ri<<1].lian0,max(t[ri<<1|1].lian0,t[ri<<1].rmax0+t[ri<<1|1].lmax0));
    t[ri].lian1=max(t[ri<<1].lian1,max(t[ri<<1|1].lian1,t[ri<<1].rmax1+t[ri<<1|1].lmax1));
    return;
}
void build(int l,int r,int ri)
{
    t[ri].tag=t[ri].tagev=0;
    t[ri].l=l;
    t[ri].r=r;
    if(l==r)
    {
        if(a[l]==0)
        {
            t[ri].lian0=t[ri].lmax0=t[ri].rmax0=t[ri].sum0=1;
            t[ri].lian1=t[ri].lmax1=t[ri].rmax1=t[ri].sum1=0;
        }
        else
        {
            t[ri].lian0=t[ri].lmax0=t[ri].rmax0=t[ri].sum0=0;
            t[ri].lian1=t[ri].lmax1=t[ri].rmax1=t[ri].sum1=1;
        }
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,ri<<1);
    build(mid+1,r,ri<<1|1);
    pushdown(ri);
    return;
}
void c0(int ri)
{
    t[ri].lian0=t[ri].lmax0=t[ri].rmax0=t[ri].sum0=t[ri].r-t[ri].l+1;
    t[ri].lian1=t[ri].lmax1=t[ri].rmax1=t[ri].sum1=0;
    return;
}
void c1(int ri)
{
    t[ri].lian0=t[ri].lmax0=t[ri].rmax0=t[ri].sum0=0;
    t[ri].lian1=t[ri].lmax1=t[ri].rmax1=t[ri].sum1=t[ri].r-t[ri].l+1;
    return;
}
void re(int ri)
{
     swap(t[ri].lian0,t[ri].lian1);
     swap(t[ri].lmax0,t[ri].lmax1);
     swap(t[ri].rmax0,t[ri].rmax1);
     swap(t[ri].sum1,t[ri].sum0);
     return;
}
void add1(int ri);
void add0(int ri);
void reve(int ri);
void push1(int ri)
{
    t[ri].tag=0;
    if(t[ri].l==t[ri].r)
        return;
    add1(ri<<1);
    add1(ri<<1|1);
    return;
}
void push0(int ri)
{
    t[ri].tag=0;
    if(t[ri].l==t[ri].r)
        return;
    add0(ri<<1);
    add0(ri<<1|1);
    return;
}
void pushre(int ri)
{
    t[ri].tagev^=1;
    if(t[ri].l==t[ri].r)
        return;
    reve(ri<<1);
    reve(ri<<1|1);
    return;
}
void add1(int ri)
{
    t[ri].tag=2;
    t[ri].tagev=0;
    c1(ri);
    return;
}
void add0(int ri)
{
    t[ri].tag=1;
    t[ri].tagev=0;
    c0(ri);
    return;
}
void reve(int ri)
{
    if(t[ri].tag==1)
        push0(ri);
    if(t[ri].tag==2)
        push1(ri);
    re(ri);
    t[ri].tagev^=1;
    return;
}
void gai0(int l,int r,int ri)
{
    if(t[ri].tag==1)
        push0(ri);
    if(t[ri].tag==2)
        push1(ri);
    if(t[ri].tagev==1)
        pushre(ri);
    if(t[ri].l>=l&&t[ri].r<=r)
    {
         t[ri].lian0=t[ri].lmax0=t[ri].rmax0=t[ri].sum0=t[ri].r-t[ri].l+1;
         t[ri].lian1=t[ri].lmax1=t[ri].rmax1=t[ri].sum1=0;
         t[ri].tag=1;
         t[ri].tagev=0;
         return;
    }
    int mid=(t[ri].l+t[ri].r)>>1;
    if(l<=mid)
        gai0(l,r,ri<<1);
    if(r>mid)
        gai0(l,r,ri<<1|1);
        pushdown(ri);
    return;
}
void gai1(int l,int r,int ri)
{
   if(t[ri].tag==1)
        push0(ri);
    if(t[ri].tag==2)
        push1(ri);
    if(t[ri].tagev==1)
        pushre(ri);
    if(t[ri].l>=l&&t[ri].r<=r)
    {
        t[ri].lian0=t[ri].lmax0=t[ri].rmax0=t[ri].sum0=0;
         t[ri].lian1=t[ri].lmax1=t[ri].rmax1=t[ri].sum1=t[ri].r-t[ri].l+1;
         t[ri].tag=2;
         t[ri].tagev=0;
         return;
    }
    int mid=(t[ri].l+t[ri].r)>>1;
    if(l<=mid)
        gai1(l,r,ri<<1);
    if(r>mid)
        gai1(l,r,ri<<1|1);
        pushdown(ri);
    return;
}
void gaivy(int l,int r,int ri)
{
   if(t[ri].tag==1)
        push0(ri);
    if(t[ri].tag==2)
        push1(ri);
    if(t[ri].tagev==1)
        pushre(ri);
        if(t[ri].l>=l&&t[ri].r<=r)
    {
        swap(t[ri].lian0,t[ri].lian1);
        swap(t[ri].lmax0,t[ri].lmax1);
        swap(t[ri].rmax0,t[ri].rmax1);
        swap(t[ri].sum1,t[ri].sum0);
        t[ri].tagev=1;
        t[ri].tag=0;
        return;
    }
    int mid=(t[ri].l+t[ri].r)>>1;
    if(l<=mid)
        gaivy(l,r,ri<<1);
    if(r>mid)
        gaivy(l,r,ri<<1|1);
    pushdown(ri);
    return;
}
int qurry1(int l,int r,int ri)
{
    if(t[ri].tag==1)
        push0(ri);
    if(t[ri].tag==2)
        push1(ri);
    if(t[ri].tagev==1)
        pushre(ri);
    if(t[ri].l>=l&&t[ri].r<=r)
    {
        return t[ri].sum1;
    }
    int mid=(t[ri].l+t[ri].r)>>1,ans=0;
    if(l<=mid)
        ans+=qurry1(l,r,ri<<1);
    if(r>mid)
        ans+=qurry1(l,r,ri<<1|1);
    return ans;
}
int qurrylian1(int l,int r,int ri)
{
   if(t[ri].tag==1)
        push0(ri);
    if(t[ri].tag==2)
        push1(ri);
    if(t[ri].tagev==1)
        pushre(ri);
    if(l<=t[ri].l&&r>=t[ri].r)
    {
        return t[ri].lian1;
    }
    int mid=(t[ri].l+t[ri].r)>>1,ans=0;
    if(l<=mid&&r>mid)
    {
        ans+=min(mid-l+1,t[ri<<1].rmax1);
        ans+=min(r-mid,t[ri<<1|1].lmax1);
    }
    if(l<=mid)
    {
        ans=max(ans,qurrylian1(l,r,ri<<1));
    }
    if(r>mid)
    {
        ans=max(ans,qurrylian1(l,r,ri<<1|1));
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    int n,i,m;
   cin>>n>>m;
    for(i=1;i<=n;i++)
        cin>>a[i];
        build(1,n,1);
    while(m--)
    {
        int p,q,y;
        cin>>y>>p>>q;
        if(y==0)
        {
            gai0(p+1,q+1,1);
        }
        else if(y==1)
        {
            gai1(p+1,q+1,1);
        }
        else if(y==2)
        {
            gaivy(p+1,q+1,1);
        }
        else if(y==3)
        {
            cout<<qurry1(p+1,q+1,1)<<endl;
        }
        else
        {
            cout<<qurrylian1(p+1,q+1,1)<<endl;
        }
    }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值