BZOJ4592 线段树

这个题有毒 我调了3个小时 各种奇葩错 (还是我太菜了)
这题就线段树维护一个区间1的个数 0的个数 左端最长连续0 右端最长连续0 区间内最长连续0 转移的思路还是很好想的 对于那个补脑洞的操作(明明脑洞越来越多) 二分一下 再区间修改

还是得多码
(我学了假的线段树 常数大到离谱)

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m;
struct node{
    bool flag,addflag;
    int sum[2],mx,lx,rx,l,r;
    bool operator == (const node&ph) const{
        return l==ph.l&&r==ph.r;
    }
}t[N*4],null;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void pushdown(int pos,int l,int r){
    int mid=(l+r)>>1;
    t[pos<<1].flag=t[pos<<1|1].flag=t[pos].flag;
    t[pos<<1].addflag=t[pos<<1|1].addflag=1;
    t[pos<<1].sum[0]=mid-l+1,t[pos<<1|1].sum[0]=r-mid,t[pos<<1|1].sum[1]=t[pos<<1].sum[1]=0;
    if(t[pos].flag) swap(t[pos<<1|1].sum[0],t[pos<<1|1].sum[1]),swap(t[pos<<1].sum[0],t[pos<<1].sum[1]);
    t[pos<<1].mx=t[pos<<1].lx=t[pos<<1].rx=t[pos].flag?0:mid-l+1;
    t[pos<<1|1].mx=t[pos<<1|1].lx=t[pos<<1|1].rx=t[pos].flag?0:r-mid;
    t[pos].addflag=0;
}
void update(int pos,int l,int r){
    int mid=(l+r)>>1;
    t[pos].sum[0]=t[pos<<1].sum[0]+t[pos<<1|1].sum[0];
    t[pos].sum[1]=t[pos<<1].sum[1]+t[pos<<1|1].sum[1];
    t[pos].mx=max(max(max(t[pos<<1].lx,t[pos<<1|1].rx),max(t[pos<<1].mx,t[pos<<1|1].mx)),t[pos<<1].rx+t[pos<<1|1].lx);
    t[pos].lx=t[pos<<1].lx==mid-l+1?t[pos<<1].lx+t[pos<<1|1].lx:t[pos<<1].lx;
    t[pos].rx=t[pos<<1|1].rx==r-mid?t[pos<<1].rx+t[pos<<1|1].rx:t[pos<<1|1].rx;
}
void build(int pos,int l,int r){
    t[pos].l=l,t[pos].r=r,t[pos].sum[1]=r-l+1;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(pos<<1,l,mid),build(pos<<1|1,mid+1,r);
} 
void add(int pos,int l,int r,int nl,int nr,int v){
    if(l>nr||r<nl) return;
    if(l>=nl&&r<=nr){
        t[pos].addflag=1;
        t[pos].flag=v;
        t[pos].sum[0]=t[pos].mx=t[pos].lx=t[pos].rx=v?0:r-l+1;
        t[pos].sum[1]=v?r-l+1:0;
        return;
    }
    if(t[pos].addflag)pushdown(pos,l,r);
    int mid=(l+r)>>1;
    add(pos<<1,l,mid,nl,nr,v);add(pos<<1|1,mid+1,r,nl,nr,v);
    update(pos,l,r);
}
int asksum(int pos,int l,int r,int nl,int nr,int v){
    if(l>nr||r<nl) return 0;
    if(l>=nl&&r<=nr) {
        return t[pos].sum[v];
    }
    if(t[pos].addflag)pushdown(pos,l,r);
    int mid=(l+r)>>1;
    return asksum(pos<<1,l,mid,nl,nr,v)+asksum(pos<<1|1,mid+1,r,nl,nr,v);
}
node work(node x,node y){
    node p;
    if(x==null||y==null) return p=x==null?y:x;
    p.mx=max(max(max(x.lx,y.rx),max(x.mx,y.mx)),x.rx+y.lx);
    p.lx=x.lx==x.r-x.l+1?x.lx+y.lx:x.lx;
    p.rx=y.rx==y.r-y.l+1?x.rx+y.rx:y.rx;
    p.l=x.l,p.r=y.r;
    return p;
}
node askmax(int pos,int l,int r,int nl,int nr){
    if(l>nr||r<nl) return null;
    if(l>=nl&&r<=nr) return t[pos];
    if(t[pos].addflag)pushdown(pos,l,r);
    int mid=(l+r)>>1;
    node p=work(askmax(pos<<1,l,mid,nl,nr),askmax(pos<<1|1,mid+1,r,nl,nr));
    return p;
}
int main(){
    n=read(),m=read();
    build(1,1,n);
    for(int i=1,op,x,y;i<=m;i++){
        op=read();
        if(op==0){
            int x=read(),y=read();
            add(1,1,n,x,y,0);
        }
        else if(op==1){
            int l0=read(),r0=read(),l1=read(),r1=read();
            int s1=asksum(1,1,n,l0,r0,1);
            if(s1){
                add(1,1,n,l0,r0,0);
                if(asksum(1,1,n,l1,r1,0)<=s1) add(1,1,n,l1,r1,1);
                else{
                    int l=l1,r=r1;
                    while(l<r){
                        int mid=(l+r)>>1;
                        if(asksum(1,1,n,l1,mid,0)<s1) l=mid+1;
                        else r=mid;
                    }
                    add(1,1,n,l1,r,1);
                }
            }
        }
        else{
            int x=read(),y=read();
            node p=askmax(1,1,n,x,y);
            printf("%d\n",max(max(p.lx,p.rx),p.mx));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值