zoukankan      html  css  js  c++  java
  • BZOJ 1858: [Scoi2010]序列操作 [线段树]

    可恶两个标记传反顺序了一直到现在....

    睡觉了睡觉了

    这是我写过最漂亮的线段树


    [补题解]

    想法很简单的线段树,同时维护0,1两个信息

    因为要求最长0,1序列所以要维护最长,从左开始最长,从右开始最长

    然后为了转移还要维护一个区间长度(该死一开始没维护这个长度后来有的地方加上有的地方没加然后一堆bug改了好久)

    我用了合并和返回节点的方法,要不然写三个询问太恶心了

    关于两个标记,显然打修改标记时要清空翻转标记,我打翻转标记时把修改标记也翻转了,所以下传标记如果先修改后翻转的话就成“翻转了两次”啊啊啊啊啊啊啊啊,以后一定要想清楚

    以后要多独立写几道复杂的题增强玛丽!

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    #define lson lc,l,mid
    #define rson rc,mid+1,r
    const int N=1e5+5;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,Q,op,a,b;
    struct Node{
        int mx[2],lm[2],rm[2],sum[2];
        int tag,rev;
        int len;
        Node():tag(-1),rev(0),len(0){mx[0]=mx[1]=lm[0]=lm[1]=rm[0]=rm[1]=sum[0]=sum[1]=0;}
    }t[N<<2];
    
    inline Node Merge(Node a,Node b){
        Node re;
        re.sum[1]=a.sum[1]+b.sum[1];
        re.mx[1]=max( a.rm[1]+b.lm[1] , max(a.mx[1],b.mx[1]) );
        re.lm[1]=a.lm[1]+ (a.lm[1]==a.len ? b.lm[1] : 0);
        re.rm[1]=b.rm[1]+ (b.rm[1]==b.len ? a.rm[1] : 0);
    
        re.sum[0]=a.sum[0]+b.sum[0];
        re.mx[0]=max( a.rm[0]+b.lm[0] , max(a.mx[0],b.mx[0]) );
        re.lm[0]=a.lm[0]+ (a.lm[0]==a.len ? b.lm[0] : 0);
        re.rm[0]=b.rm[0]+ (b.rm[0]==b.len ? a.rm[0] : 0);
    
        re.len=a.len+b.len;
        return re;
    }
    inline void pushUp(int x){t[x]=Merge(t[lc],t[rc]);}
    
    void paint(int x,int v){
        t[x].tag=v;
        t[x].rev=0;
        t[x].sum[v]=t[x].mx[v]=t[x].lm[v]=t[x].rm[v]=t[x].len;
        v^=1;
        t[x].sum[v]=t[x].mx[v]=t[x].lm[v]=t[x].rm[v]=0;
    }
    void rever(int x){
        t[x].rev^=1;
        if(t[x].tag!=-1) t[x].tag^=1;
        swap(t[x].sum[0],t[x].sum[1]);
        swap(t[x].mx[0] ,t[x].mx[1]);
        swap(t[x].lm[0] ,t[x].lm[1]);
        swap(t[x].rm[0] ,t[x].rm[1]);
    }
    
    void pushDown(int x){
        if(t[x].rev){
            rever(lc);
            rever(rc);
            t[x].rev=0;
        }
        if(t[x].tag!=-1){
            paint(lc,t[x].tag);
            paint(rc,t[x].tag);
            t[x].tag=-1;
        }
    }
    
    void build(int x,int l,int r){
        if(l==r) t[x].len=1,paint(x,read());
        else{
            build(lson);
            build(rson);
            pushUp(x);
        }
    }
    
    void segCov(int x,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr) paint(x,v);
        else{
            pushDown(x);
            if(ql<=mid) segCov(lson,ql,qr,v);
            if(mid<qr) segCov(rson,ql,qr,v);
            pushUp(x);
        }
    }
    
    void segRev(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) rever(x);
        else{
            pushDown(x);
            if(ql<=mid) segRev(lson,ql,qr);
            if(mid<qr) segRev(rson,ql,qr);
            pushUp(x);
        }
    }
    
    int segSum(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return t[x].sum[1];
        else{
            pushDown(x);
            int ans=0;
            if(ql<=mid) ans+=segSum(lson,ql,qr);
            if(mid<qr) ans+=segSum(rson,ql,qr);
            return ans;
        }
    }
    
    Node segQue(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return t[x];
        else{
            pushDown(x);
            if(qr<=mid) return segQue(lson,ql,qr);
            if(mid<ql) return segQue(rson,ql,qr);
            return Merge(segQue(lson,ql,qr),segQue(rson,ql,qr));
        }
    }
    
    int main(){
        freopen("in","r",stdin);
        n=read();Q=read();
        build(1,1,n);
        while(Q--){
            op=read();a=read()+1;b=read()+1;
            if(op==0)       segCov(1,1,n,a,b,0);
            else if(op==1) segCov(1,1,n,a,b,1);
            else if(op==2) segRev(1,1,n,a,b);
            else if(op==3) printf("%d
    ",segSum(1,1,n,a,b));
            else if(op==4) printf("%d
    ",segQue(1,1,n,a,b).mx[1]);
        }
    }
  • 相关阅读:
    DNX SDK版本 “dnx-clr-win-x86.1.0.0-beta5”无法安装
    【循序渐进MVC】第一回——一物多用Project.json依赖关系之dependencies节点
    ASP.NET页面中去除VIEWSTATE视图状态乱码
    git入门操作命令(转载)
    论火车票订单系统中并发问题和锁机制的探讨(转载)
    如何取消MSSQL自带智能提示步骤,使用第三方智能提示插件
    查看Windows服务器登录日志
    浅谈分布式计算系统和集群系统的区别
    数据库设计优化经验谈(转载)
    程序性能优化之防止装箱将拆装箱最小化
  • 原文地址:https://www.cnblogs.com/candy99/p/6487194.html
Copyright © 2011-2022 走看看