【题解】Loj #6029. 「雅礼集训 2017 Day1」市场
题目描述
数据范围1e5
题解
对于这种数据貌似可以快速缩小的题目,我们可以用势能分析来证明其某暴力或者什么做法的复杂度。
设某节点的势能函数是点内数的极差,每次除一个数极差一定会减半,总共会被除 次。
然而有特殊情况,如果考虑下取整产生的误差,可能有除法之后极差不变的情况。
如 5,6,5,6 ,在除以 3 之后变为 2,3,2,3 加上 3 之后又变回 5,6,5,6。
这样,每次除法操作都需要暴力,复杂度退化。
我们发现,下取整最多带来 1 的偏差,所以极差为 1 时才有可能除完极差不变。
于是我们可以维护最值,当最大值和最小值除d与原来数的差不变时,可以直接替换为加法操作。
有一道差不多的题,是把除法操作替换成根号。
类似的还有取min,max的,都可以用势能分析。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ls (u*2)
#define rs (u*2+1)
inline int rd(){
int f=1,j=0;
char w=getchar();
while(!isdigit(w)){
if(w=='-')f=-1;
w=getchar();
}
while(isdigit(w)){
j=j*10+w-'0';
w=getchar();
}
return f*j;
}
const int N=100010;
int n,m,sum[N];
int len[N*4],ma[N*4],mi[N*4],tag[N*4],tr[N*4];
inline void update(int u){
ma[u]=max(ma[ls],ma[rs]),mi[u]=min(mi[ls],mi[rs]);
tr[u]=tr[ls]+tr[rs];
return ;
}
inline void pushdown(int u){
if(!tag[u])return ;
tag[ls]+=tag[u],tag[rs]+=tag[u];
ma[ls]+=tag[u],ma[rs]+=tag[u],mi[ls]+=tag[u],mi[rs]+=tag[u];
tr[ls]+=tag[u]*len[ls],tr[rs]+=tag[u]*len[rs];
tag[u]=0;
return ;
}
void built(int u,int l,int r){
len[u]=r-l+1;
if(l==r)return tr[u]=ma[u]=mi[u]=sum[l],void(0);
int mid=(l+r)/2;
built(ls,l,mid),built(rs,mid+1,r);
update(u);
return ;
}
void modify1(int u,int l,int r,int L,int R,int sumn){
if(L<=l&&r<=R)return ma[u]+=sumn,mi[u]+=sumn,tag[u]+=sumn,tr[u]+=sumn*len[u],void(0);
int mid=(l+r)/2;
pushdown(u);
if(L<=mid)modify1(ls,l,mid,L,R,sumn);
if(R>mid)modify1(rs,mid+1,r,L,R,sumn);
update(u);
return ;
}
void modify2(int u,int l,int r,int L,int R,int d){
// cout<<u<<":"<<l<<" "<<r<<"-"<<L<<" "<<R<<"-"<<d<<":"<<ma[u]<<" "<<mi[u]<<"\n";
int mid=(l+r)/2;
if(l<r)pushdown(u);
if(L<=l&&r<=R){
int x=ma[u]-ma[u]/d+(ma[u]<0&&ma[u]%d!=0),y=mi[u]-mi[u]/d+(mi[u]<0&&mi[u]%d!=0);
// cout<<u<<":"<<l<<" "<<r<<"-"<<L<<" "<<R<<"-"<<d<<":"<<ma[u]<<" "<<mi[u]<<"|||"<<x<<" "<<y<<"\n";
if(x==y)return ma[u]-=x,mi[u]-=x,tag[u]-=x,tr[u]-=x*len[u],void(0);
modify2(ls,l,mid,L,R,d),modify2(rs,mid+1,r,L,R,d);
update(u);
return ;
}
if(L<=mid)modify2(ls,l,mid,L,R,d);
if(R>mid)modify2(rs,mid+1,r,L,R,d);
update(u);
return ;
}
int query3(int u,int l,int r,int L,int R){
if(L<=l&&r<=R)return mi[u];
pushdown(u);
int mid=(l+r)/2,ansn=1e18;
if(L<=mid)ansn=min(query3(ls,l,mid,L,R),ansn);
if(R>mid)ansn=min(query3(rs,mid+1,r,L,R),ansn);
return ansn;
}
int query4(int u,int l,int r,int L,int R){
if(L<=l&&r<=R)return tr[u];
pushdown(u);
int mid=(l+r)/2,ansn=0;
if(L<=mid)ansn+=query4(ls,l,mid,L,R);
if(R>mid)ansn+=query4(rs,mid+1,r,L,R);
return ansn;
}
signed main(){
// freopen("market0.in","r",stdin);
n=rd(),m=rd();
for(int i=1;i<=n;i++)sum[i]=rd();
built(1,1,n);
for(int i=1;i<=m;i++){
int k=rd();
if(k==1){
int l=rd()+1,r=rd()+1,c=rd();
modify1(1,1,n,l,r,c);
}
else if(k==2){
int l=rd()+1,r=rd()+1,d=rd();
modify2(1,1,n,l,r,d);
}
else if(k==3){
int l=rd()+1,r=rd()+1;
printf("%lld\n",query3(1,1,n,l,r));
}
else{
int l=rd()+1,r=rd()+1;
printf("%lld\n",query4(1,1,n,l,r));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具