[雅礼集训 2017 Day1]市场 题解
题目分析
听说是很典的一道题,很明显难点在于除法下取整的操作。
类似花神那一道题,但是由于有区间加,所以无法进行暴力修改。
很明显暴力复杂度爆炸,考虑下取整带来的性质:
- 对于一对相邻的数,很明显有
。 - 我们将上面的柿子稍微做一点变形,可以得到:
。
可见对于一个函数
可以用势能分析,时间复杂度大约为
#include<bits/stdc++.h> using namespace std; #define ll long long #define int long long inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x*f; } const int maxn=1e5+20; int n,a[maxn],q; struct node{ ll sum,tag1,mn,mx; }tree[maxn<<2]; struct segment_tree{ inline int ls(int x){ return x<<1; } inline int rs(int x){ return x<<1|1; } inline void push_up(int p){ tree[p].sum=tree[ls(p)].sum+tree[rs(p)].sum; tree[p].mn=min(tree[ls(p)].mn,tree[rs(p)].mn); tree[p].mx=max(tree[ls(p)].mx,tree[rs(p)].mx); } inline void push_down(int p,int l,int r){ int mid=l+r>>1; tree[ls(p)].mn+=tree[p].tag1,tree[rs(p)].mn+=tree[p].tag1; tree[ls(p)].mx+=tree[p].tag1,tree[rs(p)].mx+=tree[p].tag1; tree[ls(p)].sum+=tree[p].tag1*(mid-l+1),tree[rs(p)].sum+=tree[p].tag1*(r-mid); tree[ls(p)].tag1+=tree[p].tag1,tree[rs(p)].tag1+=tree[p].tag1; tree[p].tag1=0; } void build(int p,int l,int r){ tree[p].tag1=0; if(l==r){ tree[p].sum=tree[p].mn=tree[p].mx=a[l]; return; } int mid=l+r>>1; build(ls(p),l,mid); build(rs(p),mid+1,r); push_up(p); } void update1(int p,int l,int r,ll x,ll y,ll k){ if(x<=l&&r<=y){ tree[p].mn+=k,tree[p].mx+=k,tree[p].sum+=1ll*k*(r-l+1),tree[p].tag1+=k; return; } push_down(p,l,r); int mid=l+r>>1; if(x<=mid) update1(ls(p),l,mid,x,y,k); if(y>mid) update1(rs(p),mid+1,r,x,y,k); push_up(p); } void update2(int p,int l,int r,int x,int y,int k){ if(x<=l&&r<=y&&(ll)floor(1.0*tree[p].mx/k)-tree[p].mx==(ll)floor(1.0*tree[p].mn/k)-tree[p].mn){ tree[p].tag1+=(ll)floor(1.0*tree[p].mn/k)-tree[p].mn; tree[p].sum=tree[p].sum+((ll)floor(1.0*tree[p].mn/k)-tree[p].mn)*(r-l+1),tree[p].mn=(ll)floor(tree[p].mn*1.0/k),tree[p].mx=(ll)floor(tree[p].mx*1.0/k); return; } push_down(p,l,r); int mid=l+r>>1; if(x<=mid) update2(ls(p),l,mid,x,y,k); if(y>mid) update2(rs(p),mid+1,r,x,y,k); push_up(p); } ll query1(int p,int l,int r,int x,int y){ if(x<=l&&r<=y) return tree[p].mn; push_down(p,l,r); int mid=l+r>>1; if(y<=mid) return query1(ls(p),l,mid,x,y); if(x>mid) return query1(rs(p),mid+1,r,x,y); return min(query1(ls(p),l,mid,x,y),query1(rs(p),mid+1,r,x,y)); } ll query2(int p,int l,int r,int x,int y){ if(x<=l&&r<=y) return tree[p].sum; push_down(p,l,r); int mid=l+r>>1; if(y<=mid) return query2(ls(p),l,mid,x,y); if(x>mid) return query2(rs(p),mid+1,r,x,y); return query2(ls(p),l,mid,x,y)+query2(rs(p),mid+1,r,x,y); } }S; signed main(){ n=read(),q=read(); for(int i=0;i<n;i++) a[i+1]=read(); S.build(1,1,n); int op,l,r,x; while(q--){ op=read(),l=read(),r=read(); l++,r++; if(op==1) x=read(),S.update1(1,1,n,l,r,x); else if(op==2) x=read(),S.update2(1,1,n,l,r,x); else if(op==3) printf("%lld\n",S.query1(1,1,n,l,r)); else printf("%lld\n",S.query2(1,1,n,l,r)); } return 0; } /* */
本文作者:dayz_break
本文链接:https://www.cnblogs.com/dayz-break/p/18432317
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步