• [题解]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
    ",querym(1,1,n,l,r));
            }
            else {
                scanf("%d%d",&l,&r);l++,r++;
                printf("%lld
    ",querys(1,1,n,l,r));
            }
        }
    }
  • 相关阅读:
    Android 自定义View (一)
    Java enum的用法详解
    Android Application的使用及其生命周期
    android 支持的语言列表(汇总)
    android 使用String.format("%.2f",67.876)自已定义语言(俄语、西班牙语)会把小数点变为逗号
    TN2151:崩溃报告
    android 各国语言对应的缩写
    uva 1401 dp+Trie
    教你3网页特效免费下载栅极材料必不可少的一步,无需工具
    编译命令行终端 swift
  • 原文地址:https://www.cnblogs.com/superminivan/p/11578283.html
Copyright © 2020-2023  润新知