peiwenjun's blog 没有知识的荒原

Bear and Bad Powers of 42 题解

题目描述

定义一个正整数是坏的,当且仅当它是 \(42\) 的幂次,否则它是好的。

给定长为 \(n\) 的序列 \(a_i\) ,保证初始所有数都是好的。

接下来 \(q\) 次操作:

  • 1 i :查询 \(a_i\)
  • 2 l r x :将 \(a_l,\cdots,a_r\) 赋值为一个好的数 \(x\)
  • 3 l r x :将 \(a_l,\cdots,a_r\) 加上 \(x\) ,重复这一操作直到所有数都变好。

数据范围

  • \(1\le n,q\le 10^5\)
  • \(2\le a_i\le 10^9,1\le x\le 10^9\)

时间限制 \(\texttt{5s}\) ,空间限制 \(\texttt{256MB}\)

分析

势能线段树经典题目。

值域大约是 \(v=nq=10^{14}\) 级别,坏的数不超过 \(\log_{42}v=8\) 个。

定义势能 \(\varphi\) 为线段树所有节点的坏数个数之和,则 \(\varphi\le 8n\log n\)

对线段树每个节点,维护 \(val\) 表示区间内 \(a_i\) 到下一个坏数的最短距离,操作二直接打标记,操作三如果 \(x\lt val\) 也可以打标记,否则暴力递归,以 \(1\) 的代价让 \(\varphi\) 减少 \(1\)

时间复杂度 \(\mathcal O(n\log_{42}v+q)\log n\)

#include<bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int maxn=1e5+5;
int n,q;
int a[maxn];
struct node
{
    int l,r;
    int add,cov,val;
}f[4*maxn];
int get(int x)
{
    for(int i=1;;i*=42) if(i>=x) return i-x;
}
void pushcov(int p,int v)
{
    f[p].add=0,f[p].cov=v,f[p].val=get(v);
}
void pushadd(int p,int v)
{
    if(f[p].cov) return pushcov(p,f[p].cov+v);
    assert(v<f[p].val);
    f[p].add+=v,f[p].val-=v;
}
void pushdown(int p)
{
    if(f[p].cov) pushcov(ls,f[p].cov),pushcov(rs,f[p].cov),f[p].cov=0;
    if(f[p].add) pushadd(ls,f[p].add),pushadd(rs,f[p].add),f[p].add=0;
}
void pushup(int p)
{
    f[p].val=min(f[ls].val,f[rs].val);
}
void build(int p,int l,int r)
{
    f[p].l=l,f[p].r=r;
    if(l==r) return f[p].cov=a[l],f[p].val=get(a[l]),void();
    int mid=(l+r)>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pushup(p);
}
void modify(int p,int l,int r,int x)
{
    if(l>f[p].r||r<f[p].l) return ;
    if(l<=f[p].l&&f[p].r<=r) return pushcov(p,x);
    pushdown(p);
    modify(ls,l,r,x),modify(rs,l,r,x);
    pushup(p);
}
void update(int p,int l,int r,int x)
{
    if(l>f[p].r||r<f[p].l) return ;
    if(l<=f[p].l&&f[p].r<=r&&(x<f[p].val||f[p].cov)) return pushadd(p,x);
    pushdown(p);
    update(ls,l,r,x),update(rs,l,r,x);
    pushup(p);
}
int query(int p,int pos)
{
    if(f[p].l==f[p].r) return f[p].cov;
    int mid=(f[p].l+f[p].r)>>1;
    pushdown(p);
    return query(pos<=mid?ls:rs,pos);
}
signed main()
{
    scanf("%lld%lld",&n,&q);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,1,n);
    for(int op=0,l=0,r=0,x=0;q--;)
    {
        scanf("%lld",&op);
        if(op==1) scanf("%lld",&x),printf("%lld\n",query(1,x));
        if(op==2) scanf("%lld%lld%lld",&l,&r,&x),modify(1,l,r,x);
        if(op==3)
        {
            scanf("%lld%lld%lld",&l,&r,&x);
            do update(1,l,r,x);
            while(!f[1].val);
        }
    }
    return 0;
}

posted on 2025-01-22 23:33  peiwenjun  阅读(14)  评论(0)    收藏  举报

导航