zoukankan      html  css  js  c++  java
  • CF679E Bear and Bad Powers of 42

    一段时间不写线段树标记,有些生疏了

    codeforces 679e Bear and Bad Powers of 42 - CHADLZX - 博客园

    关键点是:42的次幂,在long long范围内只有11个

    考虑暴力修改

    记录每个点距离下一个42次幂的距离,一般是负数

    再记录每个点的等级,则有num=mi[lev+1]+val

    特别地,当val=0的时候,num就是第lev个42的次幂

    假如只有3操作,区间加,如果当前区间最大值大于等于0,

    那么暴力下去升级:如果区间最大值大于等于0,就接着升级。如果升级途中,发现一个点的val==0,意味着还要再进行这个操作,flag记录一下

    每个数只增不减,而且不会重复加太多次,大概每个点最多会被加O(logn)次,复杂度就是O(nlog^2n)

     

    加上2操作,区间赋值会把很多数“拉回来”,而且一次性增加很多42次幂

    但是权值种类会少很多,至少整个区间都是一个数

    所以记录区间是否都是一个数,如果是一个数,就不用暴力修改了

    增加了常数个42次幂的可能,也不会太多

    这一步也就O(nlogn)

    1的询问就是O(nlogn)

    总复杂度正确

    代码:

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    #define mid ((l+r)>>1)
    #define ls (x<<1)
    #define rs (x<<1|1)
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=100000+5;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    int n,q;
    int U;
    ll a[N];
    ll mi[11];
    pair<ll,ll> zip(ll x){
        int p=lower_bound(mi,mi+U+1,x)-mi;
        --p;
        return make_pair(p,x-mi[p+1]);
    }
    ll num(int lev,ll dis){
        return mi[lev+1]+dis;
    }
    struct tr{
        ll mx;
        
        ll ad,chan;    
        
        int same;
        int lev;ll val;
    }t[4*N];
    
    void pushup(int x){
        t[x].mx=max(t[x<<1].mx,t[x<<1|1].mx);
        if(t[x<<1].same&&t[x<<1|1].same&&t[x<<1].val==t[x<<1|1].val&&t[x<<1].lev==t[x<<1|1].lev){
            t[x].same=1;
            t[x].val=t[x<<1].val;
            t[x].lev=t[x<<1].lev;
        }else{
            t[x].same=0;
        }
    }
    pair<ll,ll>tmp;
    void pro(int &lev,ll &dis){
        ll now=num(lev,dis);
        tmp=zip(now);
        lev=tmp.fi;
        dis=tmp.se;
    }
    void build(int x,int l,int r){
        if(l==r){
            t[x].same=1;
            tmp=zip(a[l]);
            t[x].mx=t[x].val=tmp.se;
            t[x].lev=tmp.fi;
            t[x].chan=-inf;//warninig!!!! -inf represented no change 
            t[x].ad=0;
            return;
        }
        t[x].ad=0;
        t[x].chan=-inf;
        build(ls,l,mid);build(rs,mid+1,r);
        pushup(x);
    }
    void pushdown(int x){
        for(reg i=0;i<=1;++i){
            int son=x<<1|i;
            if(t[x].chan!=-inf){
                ll c=t[x].chan;
                t[son].same=1;
                tmp=zip(c);
                t[son].lev=tmp.fi;
                t[son].val=tmp.se;
                t[son].ad=0;
                t[son].chan=c;
                t[son].mx=t[son].val;
            }else if(t[x].ad){
                ll c=t[x].ad;
                if(t[son].same){
                    //if(t[x].mx+c==0) c+=c;//warning!!!
                    
                    if(t[son].chan!=-inf){
                        t[son].chan+=c;
                    }
                    else{
                        t[son].ad+=c;
                    }
                    t[son].val+=c;
                    pro(t[son].lev,t[son].val);
                    t[son].mx=t[son].val;
                }
                else{
                    t[son].mx+=c;
                    t[son].ad+=c;
                }
            }
        }
        t[x].ad=0;
        t[x].chan=-inf;
    }
    bool upda(int x,int l,int r){//bao li updaing level
        if(l==r){
            if(t[x].val==0){
                return true;
            }
            return false;
        }
        else if(t[x].same){
            if(t[x].val==0) return true;
            return false;
        }
        pushdown(x);
        bool ret=false;
        if(t[ls].mx>=0) ret|=upda(x<<1,l,mid);
        if(t[rs].mx>=0) ret|=upda(x<<1|1,mid+1,r);
        pushup(x);//warinnig!!!! 
        return ret; 
    }
    
    int flag;
    void add(int x,int l,int r,int L,int R,ll c){
        if(L<=l&&r<=R){
            if(t[x].same){
                if(t[x].chan!=-inf){
                    t[x].chan+=c;
                }
                else{
                    t[x].ad+=c;
                }
                t[x].val+=c;
                pro(t[x].lev,t[x].val);
                t[x].mx=t[x].val;
                
                if(t[x].mx==0) flag=1;//need again
            }
            else{
                t[x].mx+=c;
                t[x].ad+=c;
                if(t[x].mx>=0){
                    flag|=upda(x,l,r);
    //                while(fl){
    //                    fl=upda(x,l,r);
    //                    if(fl) {
    //                        t[x].mx+=c;
    //                        t[x].ad+=c;
    //                    }
    //                    if(t[x].mx>=0){
    //                        fl=true;
    //                    }else{
    //                        fl=false;
    //                    }
    //                }
                }
            }
            return;
        }
        pushdown(x);
        if(L<=mid) add(x<<1,l,mid,L,R,c);
        if(mid<R) add(x<<1|1,mid+1,r,L,R,c);
        pushup(x);
    }
    void chan(int x,int l,int r,int L,int R,ll c){
        if(L<=l&&r<=R){
            t[x].same=1;
            tmp=zip(c);
            t[x].lev=tmp.fi;
            t[x].val=tmp.se;
            t[x].ad=0;
            t[x].chan=c;
            t[x].mx=t[x].val;
            return;
        }
        pushdown(x);
        if(L<=mid) chan(x<<1,l,mid,L,R,c);
        if(mid<R) chan(x<<1|1,mid+1,r,L,R,c);
        pushup(x);
    }
    ll query(int x,int l,int r,int p){
        if(l==r){
            return num(t[x].lev,t[x].val);
        }
        pushdown(x);
        if(p<=mid) return query(ls,l,mid,p);
        else return query(rs,mid+1,r,p);
    }
    int main(){
        rd(n);rd(q);
        for(reg i=1;i<=n;++i){
            scanf("%lld",&a[i]);
        }
        mi[0]=1;
        for(reg i=1;i<=10;++i) mi[i]=mi[i-1]*42;
        U=10;
        build(1,1,n);
        int op,l,r,p;
        ll c;
        while(q--){
            rd(op);
            if(op==1){
                rd(p);
                printf("%lld
    ",query(1,1,n,p));
            }
            else if(op==2){
                rd(l);rd(r);
                scanf("%lld",&c);
                chan(1,1,n,l,r,c);
            }else{
                rd(l);rd(r);
                scanf("%lld",&c);
                flag=0;
                add(1,1,n,l,r,c);
                while(flag){
                    flag=0;
                    add(1,1,n,l,r,c);
                }
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/14 20:07:14
    */

     

  • 相关阅读:
    [Robot Framework] Robot Framework用Execute Javascript对XPath表示的元素执行scrollIntoView操作
    一台机器管理其他都装有kvm的实体机的虚拟机
    阿里云服务器问题
    开发族的跨域问题
    mysql不能连接的原因
    网络命令
    mysql5.7报错端口占用,服务起不来
    nagios的原理及server端跟client端安装配置全部过程
    查看CPU数量和核心数
    iptables的生产场景w
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10381038.html
Copyright © 2011-2022 走看看