zoukankan      html  css  js  c++  java
  • BZOJ4592 SHOI2015脑洞治疗仪(线段树)

      考虑需要资瓷哪些操作:区间赋值为0;统计区间1的个数;将区间前k个0变为1;询问区间最长全0子串。于是线段树维护区间1的个数、0的个数、最长前缀后缀全0子串即可。稍微困难的是用一个log实现将区间前k个0变为1,线段树上二分尽量往左边改即可,可以令修改函数返回值为剩余能改的1的个数。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int n,m,L[N<<2],R[N<<2];
    struct data{int sum0,sum1,pre,suf,len,lazy;
    }tree[N<<2];
    void update(int k,int x)
    {
        if (x==0)
        {
            tree[k].sum0=tree[k].pre=tree[k].suf=tree[k].len=R[k]-L[k]+1;
            tree[k].sum1=0;
        }
        else
        {
            tree[k].sum0=tree[k].pre=tree[k].suf=tree[k].len=0;
            tree[k].sum1=R[k]-L[k]+1;
        }
        tree[k].lazy=x;
    }
    void up(int k) 
    {
        tree[k].sum0=tree[k<<1].sum0+tree[k<<1|1].sum0;
        tree[k].sum1=tree[k<<1].sum1+tree[k<<1|1].sum1;
        if (tree[k<<1].pre==R[k<<1]-L[k<<1]+1) tree[k].pre=tree[k<<1].pre+tree[k<<1|1].pre;
        else tree[k].pre=tree[k<<1].pre;
        if (tree[k<<1|1].suf==R[k<<1|1]-L[k<<1|1]+1) tree[k].suf=tree[k<<1|1].suf+tree[k<<1].suf;
        else tree[k].suf=tree[k<<1|1].suf;
        tree[k].len=max(max(tree[k<<1].len,tree[k<<1|1].len),tree[k<<1].suf+tree[k<<1|1].pre);
    }
    void down(int k)
    {
        update(k<<1,tree[k].lazy);
        update(k<<1|1,tree[k].lazy);
        tree[k].lazy=-1;
    }
    void build(int k,int l,int r)
    {
        L[k]=l,R[k]=r;tree[k].lazy=-1;
        if (l==r) {tree[k].sum1=1;return;}
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        up(k);
    }
    void modify(int k,int l,int r)
    {
        if (L[k]==l&&R[k]==r) {update(k,0);return;}
        if (~tree[k].lazy) down(k);
        int mid=L[k]+R[k]>>1;
        if (r<=mid) modify(k<<1,l,r);
        else if (l>mid) modify(k<<1|1,l,r);
        else modify(k<<1,l,mid),modify(k<<1|1,mid+1,r);
        up(k);
    }
    int calc(int k,int l,int r)
    {
        if (L[k]==l&&R[k]==r) return tree[k].sum1;
        if (~tree[k].lazy) down(k);
        int mid=L[k]+R[k]>>1;
        if (r<=mid) return calc(k<<1,l,r);
        else if (l>mid) return calc(k<<1|1,l,r);
        else return calc(k<<1,l,mid)+calc(k<<1|1,mid+1,r);
    }
    int query(int k,int l,int r)
    {
        if (L[k]==l&&R[k]==r) return tree[k].len;
        if (~tree[k].lazy) down(k);
        int mid=L[k]+R[k]>>1;
        if (r<=mid) return query(k<<1,l,r);
        else if (l>mid) return query(k<<1|1,l,r);
        else return max(max(query(k<<1,l,mid),query(k<<1|1,mid+1,r)),min(tree[k<<1].suf,mid-l+1)+min(tree[k<<1|1].pre,r-mid));
    }
    int paint(int k,int l,int r,int x)
    {
        if (!x) return 0;
        if (L[k]==l&&R[k]==r&&x>=tree[k].sum0) {x-=tree[k].sum0;update(k,1);return x;}
        if (~tree[k].lazy) down(k);
        int mid=L[k]+R[k]>>1;
        if (r<=mid) x=paint(k<<1,l,r,x);
        else if (l>mid) x=paint(k<<1|1,l,r,x);
        else
        {
            int t=paint(k<<1,l,mid,x);
            if (t>=0) x=paint(k<<1|1,mid+1,r,t);
            else x=0;
        }
        up(k);
        return x;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4592.in","r",stdin);
        freopen("bzoj4592.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        build(1,1,n);
        while (m--)
        {
            int op=read(),l=read(),r=read();
            if (op==0) modify(1,l,r);
            else if (op==1)
            {
                int x=read(),y=read();
                int k=calc(1,l,r);
                modify(1,l,r);
                paint(1,x,y,k);
            }
            else printf("%d
    ",query(1,l,r));
        }
        return 0;
    }
  • 相关阅读:
    Hibernate缓存之初探
    Oracle、MySql、SQLServer 数据分页查询
    LISTAGG WITHIN GROUP函数使用方法
    exp/imp密码特殊字符处理
    Oracle动态授权用户权限
    Centos7二进制安装Mysql8.0.14
    Zabbix监控Windows网卡流量
    Zabbix监控通过jvm插件监控Tomcat
    Linux安装RabbitMQ3.73开启插件shovel并做配置
    yum安装指定路径和配置文件出错
  • 原文地址:https://www.cnblogs.com/Gloid/p/9899991.html
Copyright © 2011-2022 走看看