zoukankan      html  css  js  c++  java
  • [雅礼集训 2017 Day1]市场

    link

    试题分析

    可以容易发现此题维护的是一个数据结构,支持区间加,区间除,区间查询最大值。其实就是在$log$级复杂度内维护除法操作。

    我们发现当除数很大或者此串序列大小差不多时,我们令$a_i$为原来,$b_i$为现在,则对于$[l,r]$中的任意一个数$i$,则出现$a_i-b_i$为恒值。则我们可以用线段树去维护即可。

    举个例子:

    当我们要在$1,2,3,4,5$中每一个数除以$1$时,我们可以发现每个数都$a_i-b_i=0$,所以做区间减法即可

    当我们要在$2,3,3,3,3$中每一个数除以$2$时,$a_i-b_i=2$.所以此段区间每个数减$2$即可。

    那我们则么快速寻找是否会一样,我们只要看一下当前序列最大值与最小值的变化即可,因为他们是具有代表性的。

    然后就只要维护一个区间修改,最大值,最小值,区间查询的线段树即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<climits>
    #define int long long
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    const int N=100001;
    int n,q;
    int val[N],maxn[N<<2],minn[N<<2],sum[N<<2],tag[N<<2];
    void pushup(int k){
        maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
        minn[k]=min(minn[k<<1],minn[k<<1|1]);
        sum[k]=sum[k<<1]+sum[k<<1|1];
    }
    void build(int k,int l,int r){
        if(l==r){maxn[k]=minn[k]=sum[k]=val[l];return;}
        int mid=l+r>>1;
        build(k<<1,l,mid),build(k<<1|1,mid+1,r);
        pushup(k);
        return; 
    }
    void pushdown(int k,int l,int r){
        if(tag[k]==0) return;
        int mid=l+r>>1;
        sum[k<<1]+=(mid-l+1)*tag[k],sum[k<<1|1]+=(r-mid)*tag[k];
        maxn[k<<1]+=tag[k],minn[k<<1]+=tag[k];
        maxn[k<<1|1]+=tag[k],minn[k<<1|1]+=tag[k];
        tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k];
        tag[k]=0;
        return; 
    }
    void add(int k,int l,int r,int x,int y,int w){
    //    cout<<"l:"<<l<<" r:"<<r<<" w:"<<w<<endl;
        if(x<=l&&r<=y){
            maxn[k]+=w,minn[k]+=w,tag[k]+=w;sum[k]+=(r-l+1)*w;
            return;
        }
        pushdown(k,l,r);
        int mid=l+r>>1;
        if(x<=mid) add(k<<1,l,mid,x,y,w);
        if(mid<y) add(k<<1|1,mid+1,r,x,y,w);
        pushup(k);
        return;  
    }
    void div(int k,int l,int r,int x,int y,int w){
        if(x<=l&&r<=y){
            int s1=maxn[k]-(int)floor((double)maxn[k]/(double)w),s2=minn[k]-(int)floor((double)minn[k]/(double)w);
            if(s1==s2){
                tag[k]-=s1;sum[k]-=(r-l+1)*s1;maxn[k]-=s1,minn[k]-=s1;
                return;
            } 
        }
        pushdown(k,l,r);
        int mid=l+r>>1;
        if(x<=mid) div(k<<1,l,mid,x,y,w);
        if(mid<y) div(k<<1|1,mid+1,r,x,y,w);
        pushup(k);
        return;
    }
    int query_minn(int k,int l,int r,int x,int y){
        if(x<=l&&r<=y) return minn[k];
        int res=LLONG_MAX,mid=l+r>>1;
        pushdown(k,l,r);
        if(x<=mid) res=min(res,query_minn(k<<1,l,mid,x,y));
        if(mid<y) res=min(res,query_minn(k<<1|1,mid+1,r,x,y));
        pushup(k);
        return res;
    }
    int query_sum(int k,int l,int r,int x,int y){
        if(x<=l&&r<=y) return sum[k];
        pushdown(k,l,r);
        int res=0,mid=l+r>>1;
        if(x<=mid) res+=query_sum(k<<1,l,mid,x,y);
        if(mid<y) res+=query_sum(k<<1|1,mid+1,r,x,y);
        pushup(k);
        return res;
    }
    void find1(int k,int l,int r){
        if(l==r){cout<<maxn[k]<<" ";return;}
        int mid=l+r>>1;
        pushdown(k,l,r);
        find1(k<<1,l,mid),find1(k<<1|1,mid+1,r);
        pushup(k);
        return;
    }
    signed main(){
        n=read(),q=read();
        for(int i=1;i<=n;i++) val[i]=read();
        build(1,1,n);
        while(q--){
            int opt=read(),l=read()+1,r=read()+1;
            if(opt==1) {
                int w=read();
                add(1,1,n,l,r,w);
            }
            if(opt==2){
                int w=read();
                div(1,1,n,l,r,w);
            }
            if(opt==3) printf("%lld
    ",query_minn(1,1,n,l,r));
            if(opt==4) printf("%lld
    ",query_sum(1,1,n,l,r)); 
        }
    }
    View Code
  • 相关阅读:
    JavaScript与C# Windows应用程序交互
    用DateTime.ToString(string format)输出不同格式的日期
    时间间隔与暂停
    C#中比较两个时间的时间差
    lambda函数的用法
    Tornado笔记
    DjangoWeb应用开发实战笔记
    再看装饰器
    描述符
    flask简单代码回顾
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/10125446.html
Copyright © 2011-2022 走看看