zoukankan      html  css  js  c++  java
  • [题解]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));
            }
        }
    }
  • 相关阅读:
    volley框架使用
    Insert Interval
    candy(贪心)
    Best Time to Buy and Sell Stock
    Best Time to Buy and Sell Stock III
    distinct subsequences
    edit distance(编辑距离,两个字符串之间相似性的问题)
    trapping rain water
    word break II(单词切分)
    sudoku solver(数独)
  • 原文地址:https://www.cnblogs.com/superminivan/p/11578283.html
Copyright © 2011-2022 走看看