CF679E Bear and Bad Powers of 42

2019/02/14 22:07
阅读数 219

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

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\n",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
*/

 

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部