裸的Segment Tree Beats,给每个节点维护一个
l
a
y
e
r
layer
layer,表示当前权值所在的层(第一个不小于它的
42
42
42的幂)和距离幂最小的
d
i
s
dis
dis,再维护一个区间加标记和区间赋值标记,每次区间赋值
x
x
x直接改,区间加
x
x
x的话到区间底层尝试递归,递归到有赋值标记或者
d
i
s
dis
dis大于等于
x
x
x的位置就行了。
复杂度简单势能分析一下就是
O
(
n
log
n
+
q
log
2
n
)
\mathcal O(n\log n+q\log ^2n)
O(nlogn+qlog2n)。不过我写的比较蠢,可能会退化到三个
log
\log
log,不过没被卡。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll powd[100];
void pre() {
int cnt=0;
powd[0]=1;
while (powd[cnt]<1e16) {
cnt++;
powd[cnt]=powd[cnt-1]*42LL;
}
}
int fir[100005];
namespace SGT {
ll setv[400000],addv[400000];
ll mind[400000];
int dep[400000];
inline void pushdown(int o) {
if (setv[o]!=-1) {
setv[o*2]=setv[o*2+1]=setv[o];
mind[o*2]=mind[o*2+1]=mind[o];
dep[o*2]=dep[o*2+1]=dep[o];
addv[o*2]=addv[o*2+1]=0;
setv[o]=-1;
}
if (addv[o]) {
if (setv[o*2]!=-1) setv[o*2]+=addv[o];
else addv[o*2]+=addv[o];
if (setv[o*2+1]!=-1) setv[o*2+1]+=addv[o];
else addv[o*2+1]+=addv[o];
mind[o*2]-=addv[o];mind[o*2+1]-=addv[o];
addv[o]=0;
}
}
inline void pushup(int o) {
mind[o]=min(mind[o*2],mind[o*2+1]);
}
void build(int l,int r,int o) {
setv[o]=-1;
if (l==r) {
setv[o]=fir[l];dep[o]=addv[o]=0;
while (powd[dep[o]]<setv[o]) dep[o]++;
mind[o]=powd[dep[o]]-setv[o];
}
else {
int m=((l+r)>>1);
build(l,m,o*2);
build(m+1,r,o*2+1);
pushup(o);
}
}
void update1(int l,int r,int o,int lx,int rx,int p) {
if (l>=lx&&r<=rx) {
setv[o]=p;dep[o]=addv[o]=0;
while (powd[dep[o]]<setv[o]) dep[o]++;
mind[o]=powd[dep[o]]-setv[o];
}
else {
pushdown(o);
int m=((l+r)>>1);
if (m>=lx) update1(l,m,o*2,lx,rx,p);
if (m<rx) update1(m+1,r,o*2+1,lx,rx,p);
pushup(o);
}
}
void dfs(int l,int r,int o,int p) {
if (setv[o]!=-1) {
setv[o]+=p;
while (powd[dep[o]]<setv[o]) dep[o]++;
mind[o]=powd[dep[o]]-setv[o];
}
else if (mind[o]>=p) {
addv[o]+=p;
mind[o]-=p;
}
else {
pushdown(o);
int m=((l+r)>>1);
dfs(l,m,o*2,p);
dfs(m+1,r,o*2+1,p);
pushup(o);
}
}
void update2(int l,int r,int o,int lx,int rx,int p) {
if (l>=lx&&r<=rx) dfs(l,r,o,p);
else {
pushdown(o);
int m=((l+r)>>1);
if (m>=lx) update2(l,m,o*2,lx,rx,p);
if (m<rx) update2(m+1,r,o*2+1,lx,rx,p);
pushup(o);
}
}
ll query1(int l,int r,int o,int p) {
if (setv[o]!=-1) return setv[o];
else {
pushdown(o);
int m=((l+r)>>1);
if (m>=p) return query1(l,m,o*2,p);
else return query1(m+1,r,o*2+1,p);
}
}
bool query2(int l,int r,int o,int lx,int rx) {
if (l>=lx&&r<=rx) return mind[o]==0;
else {
pushdown(o);
int m=((l+r)>>1);
if (m>=rx) return query2(l,m,o*2,lx,rx);
if (m<lx) return query2(m+1,r,o*2+1,lx,rx);
return query2(l,m,o*2,lx,rx)|query2(m+1,r,o*2+1,lx,rx);
}
}
}
int main() {
pre();
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&fir[i]);
SGT::build(1,n,1);
for(int i=1;i<=m;i++) {
int kind;
scanf("%d",&kind);
if (kind==1) {
int x;
scanf("%d",&x);
printf("%lld\n",SGT::query1(1,n,1,x));
}
else if (kind==2) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
SGT::update1(1,n,1,x,y,z);
}
else {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
do {
SGT::update2(1,n,1,x,y,z);
} while (SGT::query2(1,n,1,x,y));
}
}
return 0;
}