[题解]LOJ_6029市场(线段树区间加/除
作者:互联网
https://www.cnblogs.com/scx2015noip-as-php/p/loj6029.html
一开始以为裸的区间除,维护这一段是否全为0,后来发现还有加法,这样就会被卡了
这题除数达到了1e9,题解说在数很小除数很大的时候区间除会变成区间减,如一段序列由$x,x-1$组成,除一个$d$相当于减去了同样的变化量
所以我们需要维护区间最大最小值,每次判断最大值和最小值除完之后差是否一样,不一样递归
(我自己反正想不出来)
#include<bits/stdc++.h> #define ls (x<<1) #define rs (x<<1|1) #define mid ((l+r)>>1) #define ll long long using namespace std; const int maxn=100009; int n,m; struct node{ ll sum,mn,tg,mx;//是否没除到0 }t[maxn<<2]; inline ll min(ll a,ll b){return a<b?a:b;} inline ll max(ll a,ll b){return a>b?a:b;} inline void upd(int x){ t[x].mn=min(t[ls].mn,t[rs].mn); t[x].mx=max(t[ls].mx,t[rs].mx); t[x].sum=t[ls].sum+t[rs].sum; } void build(int x,int l,int r){ if(l==r){ scanf("%lld",&t[x].sum); t[x].mx=t[x].mn=t[x].sum; return; } build(ls,l,mid);build(rs,mid+1,r); upd(x); } inline void pd(int x,int l,int r){ if(t[x].tg){ t[ls].tg+=t[x].tg; t[rs].tg+=t[x].tg; t[ls].sum+=t[x].tg*(mid-l+1); t[rs].sum+=t[x].tg*(r-mid); t[ls].mn+=t[x].tg; t[rs].mn+=t[x].tg; t[ls].mx+=t[x].tg; t[rs].mx+=t[x].tg; t[x].tg=0; } } void changea(int x,int l,int r,int L,int R,ll k){ if(L<=l && r<=R){ t[x].tg+=k; t[x].sum+=k*(r-l+1); t[x].mn+=k;t[x].mx+=k; return; } pd(x,l,r); if(L<=mid)changea(ls,l,mid,L,R,k); if(R>mid)changea(rs,mid+1,r,L,R,k); upd(x); } void changeb(int x,int l,int r,int L,int R,ll d){ if(L<=l && r<=R){ ll d1=t[x].mx-floor((double)t[x].mx/d), d2=t[x].mn-floor((double)t[x].mn/d); //转化为区间减 if(d1==d2){ t[x].tg-=d1,t[x].sum-=d1*(r-l+1); t[x].mx-=d1,t[x].mn-=d1; return; } } pd(x,l,r); if(L<=mid)changeb(ls,l,mid,L,R,d); if(R>mid)changeb(rs,mid+1,r,L,R,d); upd(x); } ll querys(int x,int l,int r,int L,int R){ if(L<=l && r<=R)return t[x].sum; pd(x,l,r); ll ans=0; if(L<=mid)ans+=querys(ls,l,mid,L,R); if(R>mid)ans+=querys(rs,mid+1,r,L,R); return ans; } ll querym(int x,int l,int r,int L,int R){ if(L<=l && r<=R)return t[x].mn; pd(x,l,r); ll ans=1e18; if(L<=mid)ans=min(ans,querym(ls,l,mid,L,R)); if(R>mid)ans=min(ans,querym(rs,mid+1,r,L,R)); return ans; } int main(){ scanf("%d%d",&n,&m); build(1,1,n);ll l,r,d,op; for(int i=1;i<=m;i++){ scanf("%d",&op); if(op==1){ scanf("%lld%lld%lld",&l,&r,&d); l++,r++; changea(1,1,n,l,r,d); } else if(op==2){ scanf("%lld%lld%lld",&l,&r,&d); l++,r++; changeb(1,1,n,l,r,d); } else if(op==3){ scanf("%d%d",&l,&r);l++,r++; printf("%lld\n",querym(1,1,n,l,r)); } else { scanf("%d%d",&l,&r);l++,r++; printf("%lld\n",querys(1,1,n,l,r)); } } }
标签:6029,rs,LOJ,题解,sum,mid,int,ls,tg 来源: https://www.cnblogs.com/superminivan/p/11578283.html