「雅礼集训 2017 Day1」市场 线段树维护除法下取整
「雅礼集训 2017 Day1」市场
线段树维护除法下取整
链接
区间最小值,区间和,区间加,区间除下取整
除数巨大,不好维护
但是可以用一种方法改为做区间减法
\(1,1,2,2\)这个序列除以\(2\)下取整为\(0,0,1,1\)
\(2,2,3,3\)除以\(3\)结果\(0,0,1,1\)
第一个相当于区间减去\(1\)
第二个相当于区间减去\(2\)
所以我们可以记一下区间最大值\(mx\),最小值\(mn\)
当\(mx\)和\(mn\)的减数一样的话就可以区间减法了
别的就是普通线段树了
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int n,q,a[maxn];
struct node{
ll sum,mn,mx,pl;
#define sum(x) t[x].sum
#define mn(x) t[x].mn
#define mx(x) t[x].mx
#define pl(x) t[x].pl
}t[maxn<<2];
inline void pushup(int p){
sum(p)=sum(p<<1)+sum(p<<1|1);
mn(p)=min(mn(p<<1),mn(p<<1|1));
mx(p)=max(mx(p<<1),mx(p<<1|1));
}
void build(int p,int l,int r){
if(l==r){
sum(p)=mn(p)=mx(p)=a[l];pl(p)=0;
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
pushup(p);
}
inline void pushdown(int p,int l,int r){
if(!pl(p)) return;
int mid=(l+r)>>1;
sum(p<<1)+=(mid-l+1)*pl(p);
sum(p<<1|1)+=(r-mid)*pl(p);
mx(p<<1)+=pl(p);mx(p<<1|1)+=pl(p);
mn(p<<1)+=pl(p);mn(p<<1|1)+=pl(p);
pl(p<<1)+=pl(p);pl(p<<1|1)+=pl(p);pl(p)=0;
}
void change1(int p,int l,int r,int x,int y,int d){
if(x<=l && r<=y){
pl(p)+=d;mn(p)+=d;mx(p)+=d;sum(p)+=(r-l+1)*d;
return;
}
pushdown(p,l,r);
int mid=(l+r)>>1;
if(x<=mid) change1(p<<1,l,mid,x,y,d);
if(y>mid) change1(p<<1|1,mid+1,r,x,y,d);
pushup(p);
}
void change2(int p,int l,int r,int x,int y,int d){
if(x<=l && r<=y){
int g1=mx(p)-(ll)floor((double)mx(p)/d);
int g2=mn(p)-(ll)floor((double)mn(p)/d);
if(g1==g2){
pl(p)-=g1;sum(p)-=g1*(r-l+1);
mx(p)-=g1;mn(p)-=g1;return;
}
}
pushdown(p,l,r);
int mid=(l+r)>>1;
if(x<=mid) change2(p<<1,l,mid,x,y,d);
if(y>mid) change2(p<<1|1,mid+1,r,x,y,d);
pushup(p);
}
ll askmn(int p,int l,int r,int x,int y){
if(x<=l && r<=y) return mn(p);
pushdown(p,l,r);
int mid=(l+r)>>1;
ll res=0x7ffffff;
if(x<=mid) res=min(res,askmn(p<<1,l,mid,x,y));
if(y>mid) res=min(res,askmn(p<<1|1,mid+1,r,x,y));
return res;
}
ll asksm(int p,int l,int r,int x,int y){
if(x<=l && r<=y) return sum(p);
pushdown(p,l,r);
int mid=(l+r)>>1;
ll res=0;
if(x<=mid) res+=asksm(p<<1,l,mid,x,y);
if(y>mid) res+=asksm(p<<1|1,mid+1,r,x,y);
return res;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
while(q--){
int op;scanf("%d",&op);
if(op==1){
int l,r,c;scanf("%d%d%d",&l,&r,&c);l++;r++;
change1(1,1,n,l,r,c);
}
if(op==2){
int l,r,c;scanf("%d%d%d",&l,&r,&c);l++;r++;
change2(1,1,n,l,r,c);
}
if(op==3){
int l,r;scanf("%d%d",&l,&r);l++;r++;
printf("%lld\n",askmn(1,1,n,l,r));
}
if(op==4){
int l,r;scanf("%d%d",&l,&r);l++;r++;
printf("%lld\n",asksm(1,1,n,l,r));
}
}
return 0;
}
ps 难得的LOJ 1A