「雅礼集训 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

posted @ 2019-10-29 11:30  ChrisKKK  阅读(227)  评论(0编辑  收藏  举报