zoukankan      html  css  js  c++  java
  • SHOI2015 脑洞治疗仪

    题目链接:戳我

    luogu的题面真心好看!!!qwqwq

    按照专业的话来讲,这个题是——线段树维护最大连续子段

    好吧。。其实就和前两天写的那个区间最大字段和很相似嘛,就是左右线段树可以合并这种维护信息类型的题目。

    操作0是线段树区间赋值

    操作1是线段树区间赋值+线段树区间前K个赋值(前K个怎么实现呢?就是我们在线段树上直接二分,然后找到那些0的个数小于等于K的区间们,然后一个一个依次赋值)

    操作2是求线段树中最大相同子段长度

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define MAXN 200010
    using namespace std;
    int n,m;
    int le[MAXN<<2],ri[MAXN<<2];
    struct Node{int maxl,maxr,maxs,sum0,sum1,tag;}t[MAXN<<2];
     
    inline int ls(int x){return x<<1;}
    inline int rs(int x){return x<<1|1;}
     
    inline void update(int x,int k)
    {
        if(k==0)
        {
            t[x].sum0=t[x].maxl=t[x].maxr=t[x].maxs=ri[x]-le[x]+1;
            t[x].sum1=0;
        }
        else if(k==1)
        {
            t[x].sum1=ri[x]-le[x]+1;
            t[x].sum0=t[x].maxl=t[x].maxr=t[x].maxs=0;
        }
        t[x].tag=k;
    }
     
    inline void push_up(int x)
    {
        t[x].sum0=t[ls(x)].sum0+t[rs(x)].sum0;
        t[x].sum1=t[ls(x)].sum1+t[rs(x)].sum1;
        t[x].maxl=t[ls(x)].maxl;
        if(t[ls(x)].maxl==ri[ls(x)]-le[ls(x)]+1) t[x].maxl=max(t[x].maxl,t[ls(x)].maxl+t[rs(x)].maxl);
        t[x].maxr=t[rs(x)].maxr;
        if(t[rs(x)].maxr==ri[rs(x)]-le[rs(x)]+1) t[x].maxr=max(t[x].maxr,t[rs(x)].maxr+t[ls(x)].maxr);
        t[x].maxs=max(max(t[ls(x)].maxs,t[rs(x)].maxs),t[ls(x)].maxr+t[rs(x)].maxl);
    }
     
    inline void push_down(int x)
    {
        if(t[x].tag!=-1)
        {
            update(ls(x),t[x].tag);
            update(rs(x),t[x].tag);
            t[x].tag=-1;
        }
    }
     
    inline void build(int x,int l,int r)
    {
        t[x].tag=-1;
        le[x]=l; ri[x]=r;
        if(le[x]==ri[x]){t[x].sum1=1;return;}
        int mid=(le[x]+ri[x])>>1;
        build(ls(x),le[x],mid);
        build(rs(x),mid+1,ri[x]);
        push_up(x);
    }
     
    inline void clean(int x,int ll,int rr)
    {
        if(ll==le[x]&&ri[x]==rr) {update(x,0);return;}
        int mid=(le[x]+ri[x])>>1;
        push_down(x);
        if(rr<=mid) clean(ls(x),ll,rr);
        else if(mid<ll) clean(rs(x),ll,rr);
        else clean(ls(x),ll,mid),clean(rs(x),mid+1,rr);
        push_up(x);
    }
     
    inline int que_sum(int x,int ll,int rr)
    {
        if(ll==le[x]&&ri[x]==rr) return t[x].sum1;
        int mid=(le[x]+ri[x])>>1;
        push_down(x);
        if(rr<=mid) return que_sum(ls(x),ll,rr);
        else if(mid<ll) return que_sum(rs(x),ll,rr);
        else return que_sum(ls(x),ll,mid)+que_sum(rs(x),mid+1,rr);
    }
     
    inline int query(int x,int ll,int rr)
    {
        if(ll==le[x]&&ri[x]==rr) return t[x].maxs;
        int mid=(le[x]+ri[x])>>1;
        push_down(x);
        if(rr<=mid) return query(ls(x),ll,rr);
        else if(mid<ll) return query(rs(x),ll,rr);
        else
        {
            int cur1=query(ls(x),ll,mid);
            int cur2=query(rs(x),mid+1,rr);
            int z1=min(t[ls(x)].maxr,mid-ll+1);
            int z2=min(t[rs(x)].maxl,rr-mid);
            return max(max(cur1,cur2),z1+z2);
        }
    }
     
    inline void mend(int x,int ll,int rr,int &k)
    {
        if(k<=0) return;
        if(ll==le[x]&&ri[x]==rr&&k>=t[x].sum0)
        {
            k-=t[x].sum0;
            update(x,1);
            return;
        }
        int mid=(le[x]+ri[x])>>1;
        push_down(x);
        if(rr<=mid) mend(ls(x),ll,rr,k);
        else if(mid<ll) mend(rs(x),ll,rr,k);
        else
        {
            mend(ls(x),ll,mid,k);
            if(k>=0) mend(rs(x),mid+1,rr,k);
            else k=0;
        }
        push_up(x);
    }
     
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            int op,l,r,ll,rr;
            scanf("%d",&op);
            if(op==0)
            {
                scanf("%d%d",&l,&r);
                clean(1,l,r);
            }
            else if(op==1)
            {
                scanf("%d%d%d%d",&l,&r,&ll,&rr);
                int k=que_sum(1,l,r);
                clean(1,l,r);
                mend(1,ll,rr,k);
            }
            else   
            {
                scanf("%d%d",&l,&r);
                printf("%d
    ",query(1,l,r));
            }
        }
        return 0;
    }
    

    不过我写的原先不是把l,r写在struct里面的那种写法,是直接跟在函数里面的。但是之后发现。。。。不知道为什么它的左右区间不对应。。。之后就重构了一遍写了这种写法。。。。菜是原罪。。整天都是莫名其妙的锅qwqwq

  • 相关阅读:
    HDU-4027-Can you answer these queries?
    Python的多协程(三种简单生成多协程方法)
    关于django 如何实现简单api的restful 接口
    flask 框架服务原理
    DVWA渗透测试环境搭建
    装饰器 python 你也可以叫语法糖
    websocket python实现原理
    robotframe 自定义开发库
    mysql linux 安装卸载
    python+jenkins 构建节点环境编译器配置问题
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10418582.html
Copyright © 2011-2022 走看看