我是小丑,这道题读错了整整两次!!
还是用线段树维护。发现一个神奇的事情,这题只要能快速判断区间内是否存在
42
42
42的次幂,然后用
Segment Tree Beats
\text{Segment\ Tree\ Beats}
Segment Tree Beats维护就完了。这可以通过维护与最小的
42
42
42次幂的差值来实现,因为这样区间加时可以快速维护。
可以感性认为复杂度是对的。 根据
Segment Tree Beats
\text{Segment\ Tree\ Beats}
Segment Tree Beats的思想我们要设计势能函数来分析复杂度,但是这题的势能比较奇怪 所以就咕了。
复杂度据说是
O
(
n
log
n
log
42
V
)
O(n\log n\log_{42} V)
O(nlognlog42V)。
写了一发,发现难点在于各种标记的处理比较复杂,可能这也是本题复杂度比较难分析的原因。所以这题难度还是低估了。
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e5+5;
int n,m,a[N];
ll nums[15];
struct node{
ll min,val,tagnums;
int tag;
}t[N<<2];
void pushup(int p){
t[p].min=min(t[p<<1].min,t[p<<1|1].min);
}
ll calc(ll x){
int ps=lower_bound(nums,nums+10,x)-nums;
assert(ps<=9);return nums[ps]-x;
}
void build(int p,int l,int r){
if(l==r){
t[p].tag=1,t[p].val=a[l],t[p].min=calc(a[l]);
return;
}
int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
pushup(p);
}
void cover(int p,ll val){
t[p].tag=1,t[p].val=val,t[p].tagnums=0,t[p].min=calc(val);
}
void add(int p,ll val){
t[p].tagnums+=val,t[p].min-=val;
assert(t[p].min>=0);
}
void pushdown(int p){
if(t[p].tag){
cover(p<<1,t[p].val),cover(p<<1|1,t[p].val);
t[p].tag=0;
}
if(t[p].tagnums){
add(p<<1,t[p].tagnums),add(p<<1|1,t[p].tagnums);
t[p].tagnums=0;
}
}
void modify(int p,int l,int r,int ql,int qr,int val){
if(ql<=l&&r<=qr){
cover(p,val);
return;
}
int mid=l+r>>1;pushdown(p);
if(ql<=mid)modify(p<<1,l,mid,ql,qr,val);
if(mid<qr)modify(p<<1|1,mid+1,r,ql,qr,val);
pushup(p);
}
void addnums(int p,int l,int r,int ql,int qr,ll val){
if(ql<=l&&r<=qr&&t[p].min>=val){
add(p,val);
return;
}
if(ql<=l&&r<=qr&&t[p].tag){
cover(p,t[p].val+t[p].tagnums+val);
return;
}
if(l==r){
t[p].val+=val,t[p].min=calc(t[p].val+t[p].tagnums);
return;
}
int mid=l+r>>1;pushdown(p);
if(ql<=mid)addnums(p<<1,l,mid,ql,qr,val);
if(mid<qr)addnums(p<<1|1,mid+1,r,ql,qr,val);
pushup(p);
}
ll query(int p,int l,int r,int x){
if(l==r){
assert(t[p].tag);
return t[p].val+t[p].tagnums;
}
int mid=l+r>>1;pushdown(p);
return x<=mid?query(p<<1,l,mid,x):query(p<<1|1,mid+1,r,x);
}
ll querymin(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
assert(t[p].min>=0);
return t[p].min;
}
int mid=l+r>>1;
if(qr<=mid)return querymin(p<<1,l,mid,ql,qr);
if(mid<ql)return querymin(p<<1|1,mid+1,r,ql,qr);
return min(querymin(p<<1,l,mid,ql,qr),querymin(p<<1|1,mid+1,r,ql,qr));
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m;nums[0]=1;
for(int i=1;i<=9;i++){
nums[i]=nums[i-1]*42;
assert(nums[i]>=0);
assert(nums[i]<=1e18);
}
for(int i=1;i<=n;i++)cin>>a[i];
build(1,1,n);
for(int i=1;i<=m;i++){
int type,l,r,x;
cin>>type;
if(type==1){
cin>>x;cout<<query(1,1,n,x)<<"\n";
}
else if(type==2){
cin>>l>>r>>x;
modify(1,1,n,l,r,x);
}
else{
cin>>l>>r>>x;
addnums(1,1,n,l,r,x);
while(querymin(1,1,n,l,r)==0){
addnums(1,1,n,l,r,x);
}
}
}
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2022-07-04 【学习笔记】图的连通性与回路
2022-07-04 【简要题解】OI Online能力测试校内赛(Round One)T2~T4
2022-07-04 【学习笔记】阶段测试1