zoukankan      html  css  js  c++  java
  • 「雅礼集训 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

  • 相关阅读:
    iis环境异常处理
    cmd常用命令:关机、注销、进入d盘等
    position
    Register Form
    第一周
    Django简介
    前端jQuery基本语法
    前端基础BOM和DOM
    HTML常用标签
    Linux相关 MySQL相关
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11757760.html
Copyright © 2011-2022 走看看