「雅礼集训 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
",askmn(1,1,n,l,r));
		}
		if(op==4){
			int l,r;scanf("%d%d",&l,&r);l++;r++;
			printf("%lld
",asksm(1,1,n,l,r));
		}
	}
	return 0;
}

ps 难得的LOJ 1A

原文地址:https://www.cnblogs.com/ChrisKKK/p/11757760.html