• E


    题意

    给n,m两个数字,表示 n长度数组a 和 m个操作,数组a有一个特点,从大到小

    每个操作输入t x y

    当t==1时候,操作1->把[1,x]区间 max(a[],y);

    当t==2时候,操作2->把[x,n]区间 从x到n遍历,如果有比y小的,y减掉a[i],个数加一,然后输出可以买多少个

    就比如数组:
    10 10 7 6 1
    操作:
    t=2,x=1,y=17
    取第一个和第三个
    输出2
    

    思路

    一看就是线段树,然后因为操作二的限制,数组一定是从大到小的,那么我们判断区间最小值,最大值和区间和

    操作一,我们可以用最大值来判断是否需要lazy标记

    操作二,我们可以用递归,先递归左子树上的区间和有没有比y小,然后在递归右子树有没有比y小的

    区间最大值和区间和都有用,区间最小值呢?

    答案就是用来优化,如果你遇到y的值比区间最小值还要小,直接return了

    代码

    #include <bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define lowbit(x) x&-x
    using namespace std;
    const int N=2e5+100;
    ll ksm(ll a,ll b){
        ll ans=1;
        while(b){
            if(b&1){
                ans*=a;ans%=mod;
            }
            a*=a;a%=mod;
            b>>=1;
        }
        return ans;
    }
    int t,n,m;
    int tr[N<<2],lazy[N<<2],ge[N<<2],a[N],mi[N<<2];
    ll sum[N<<2];
    void pushup(int x){
        tr[x]=max(tr[x<<1],tr[x<<1|1]);
        mi[x]=min(mi[x<<1],mi[x<<1|1]);
        sum[x]=sum[x<<1]+sum[x<<1|1];
    }
    void pushdown(int x,int l,int r){
        if(lazy[x]){
            if(l==r){
                sum[x]=lazy[x];
                tr[x]=lazy[x];mi[x]=lazy[x];
                lazy[x]=0;
            }
            else{
                lazy[x<<1]=lazy[x];lazy[x<<1|1]=lazy[x];
                tr[x<<1]=mi[x<<1]=lazy[x];
                int mid=(l+r)>>1;
                sum[x<<1]=(ll)tr[x<<1]*(mid-l+1);
                tr[x<<1|1]=mi[x<<1|1]=lazy[x];
                sum[x<<1|1]=(ll)tr[x<<1|1]*(r-mid);
                lazy[x]=0;
            }
        }
    }
    void build(int x,int l,int r){
        lazy[x]=0;
        if(l==r){
            tr[x]=a[l];sum[x]=(ll)a[l];mi[x]=a[l];return;
        }
        int mid=(l+r)>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    void update(int x,int l,int r,int L,int R,int zhi){
        if(mi[x]>zhi){return;}
        if(L<=l && r<=R && tr[x]<=zhi){
            pushdown(x,l,r);
            lazy[x]=zhi;
            sum[x]=(ll)zhi*(r-l+1);
            tr[x]=zhi;mi[x]=zhi;
            return;
        }
        pushdown(x,l,r);
        int mid=(l+r)>>1;
        if(mid>=L){
            update(x<<1,l,mid,L,R,zhi);
        }
        if(R>mid){
            update(x<<1|1,mid+1,r,L,R,zhi);
        }
        pushup(x);
    }
    ll ans;
    int g=0;
    void querry(int x,int l,int r,int L,int R){
          if(mi[x]>ans){return;}
         if(L<=l && r<=R && sum[x]<=ans){
            pushdown(x,l,r);
            ans-=sum[x];g+=(r-l+1);//cout<<sum[x]<<endl;
            return;
         }
         pushdown(x,l,r);
         int mid=(l+r)>>1;
    
         if(mid>=L){
             querry(x<<1,l,mid,L,R);
         }
         if(R>mid){
             querry(x<<1|1,mid+1,r,L,R);
         }
         pushup(x);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        for(int i=0;i<m;i++){
            int x;scanf("%d",&x);//cout<<sum[1]<<endl;
            if(x==1){
                int r,zhi;
                scanf("%d%d",&r,&zhi);
                update(1,1,n,1,r,zhi);
            }
            else{
                int l;
                scanf("%d%lld",&l,&ans);
                g=0;querry(1,1,n,l,n);
                printf("%d
    ",g);
            }
        }
        return 0;
    }
    /*
    */
    
  • 相关阅读:
    html5 java多图片上传
    ajax post form表单
    java获取图片文件返回地址
    教你使用servlet拦截器,放行不需要拦截的内容
    实用的request接收值的工具类
    spring3的定时执行任务
    centos7.4无法启动之找不到EFIBOOTgrubx64.efi
    redhat7.2上搭建网易、epel的yum repo
    python2和python3中的关键字的区别--keyword模块
    搭建lamp的脚本
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/14048764.html
Copyright © 2020-2023  润新知