Codeforces 121 E
感觉我数据结构有些弱,最近开始练习难道为2300~2700的数据结构题。
首先我们发现,lucky number不会太多,最多就是个(最后加是对于所有的数,最近的lucky number应该是)
这里我们维护的东西有些奇特——我们维护的值,其中是大于等于最小的lucky number。
那么区间加上就相当于区间将减去。
但是有可能存在的情况,那么我们此时记录这样的位置,并且计算当前的值,暴力重新更新,此时是下一个大于等于的值。(线段树单点修改)
看起来直接记录每个的点是的,但事实上,我们每次更新都会使得变大,而最大也就是,即每个点只会暴力更新次,故总世界复杂度为。
如何找到的点?我们可以记录区间最小值,若最小值,那么意味着这个区间内一定有一个的点,继续递归即可。
如何回答询问?我们在线段树上不仅记录最小值,并且记录有多少个最小值。询问本质就是找到最小值为0的个数。
注意常数。
#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl
const int maxn=100005;
int n,q,a[maxn],now[maxn];
int nxt[10005],val[maxn<<2],lef[maxn<<2],rig[maxn<<2],sum[maxn<<2],lzy[maxn<<2];
char buf[12];
std::vector<int> need;
void pushdown(int pos) {
val[pos<<1]+=lzy[pos];
val[pos<<1|1]+=lzy[pos];
lzy[pos<<1]+=lzy[pos];
lzy[pos<<1|1]+=lzy[pos];
lzy[pos]=0;
}
void pushup(int pos) {
if(val[pos<<1]<val[pos<<1|1]) {
val[pos]=val[pos<<1];
sum[pos]=sum[pos<<1];
} else if(val[pos<<1]>val[pos<<1|1]) {
val[pos]=val[pos<<1|1];
sum[pos]=sum[pos<<1|1];
} else {
val[pos]=val[pos<<1];
sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
}
void build(int pos,int l,int r) {
lef[pos]=l,rig[pos]=r;
if(l==r) {
val[pos]=nxt[a[l]]-a[l];
sum[pos]=1;
now[l]=nxt[a[l]];
} else {
int m=l+r>>1;
build(pos<<1,l,m); build(pos<<1|1,m+1,r);
pushup(pos);
}
}
void get_change(int l,int r,int D,int pos) {
if(l<=lef[pos]&&rig[pos]<=r) {
if(val[pos]<D) {
if(lef[pos]==rig[pos]) {
need.push_back(lef[pos]);
return;
}
pushdown(pos);
get_change(l,r,D,pos<<1);
get_change(l,r,D,pos<<1|1);
pushup(pos);
}
} else if(l<=rig[pos]&&r>=lef[pos]) {
pushdown(pos);
get_change(l,r,D,pos<<1);
get_change(l,r,D,pos<<1|1);
pushup(pos);
}
}
int query(int p,int pos) {
if(lef[pos]==rig[pos]) return val[pos];
pushdown(pos); int ret;
if(rig[pos<<1]>=p) ret=query(p,pos<<1);
else ret=query(p,pos<<1|1);
pushup(pos); return ret;
}
void update(int l,int r,int D,int pos) {
if(l<=lef[pos]&&rig[pos]<=r) {
val[pos]+=D;
lzy[pos]+=D;
} else if(l<=rig[pos]&&r>=lef[pos]) {
pushdown(pos);
update(l,r,D,pos<<1);
update(l,r,D,pos<<1|1);
pushup(pos);
}
}
int get_answer(int l,int r,int pos) {
if(l<=lef[pos]&&rig[pos]<=r) {
if(val[pos]==0) {
return sum[pos];
}
} else if(l<=rig[pos]&&r>=lef[pos]) {
pushdown(pos);
int ret=get_answer(l,r,pos<<1)+get_answer(l,r,pos<<1|1);
pushup(pos);
return ret;
}
return 0;
}
int main() {
std::vector<int> lucky;
for(int i=1;i<=4;i++) {
for(int j=0;j<(1<<i);j++) {
int num=0;
for(int k=0;k<i;k++) {
if(j&(1<<k)) {
num=10*num+4;
} else {
num=10*num+7;
}
}
lucky.push_back(num);
}
}
lucky.push_back(44444);
std::sort(lucky.begin(),lucky.end());
for(int i=1;i<=10000;i++) {
nxt[i]=*std::lower_bound(lucky.begin(),lucky.end(),i);
}
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
build(1,1,n);
while(q--) {
scanf("%s",buf);
int op=strlen(buf)==5;
if(op==0) {
int l,r,x; scanf("%d%d%d",&l,&r,&x);
need.clear();
get_change(l,r,x,1);
for(auto item : need) {
int rec=query(item,1);
int num=now[item]-rec;
update(item,item,-rec+nxt[num+x]-num,1);
now[item]=nxt[num+x];
}
update(l,r,-x,1);
} else {
int l,r; scanf("%d%d",&l,&r);
printf("%d\n",get_answer(l,r,1));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话