zoukankan      html  css  js  c++  java
  • 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;
    }
    /*
    */
    
  • 相关阅读:
    .net core 3.1 使用Redis缓存
    JavaSE 高级 第11节 缓冲输入输出字节流
    JavaSE 高级 第10节 字节数组输出流ByteArrayOutputStream
    JavaSE 高级 第09节 字节数组输入流ByteArrayInputStream
    JavaSE 高级 第08节 文件输出流FileOutputStream
    JavaSE 高级 第07节 文件输入流FileInputStream
    JavaSE 高级 第06节 初识I、O流
    JavaSE 高级 第05节 日期类与格式化
    JavaSE 高级 第04节 StringBuffer类
    JavaSE 高级 第03节 Math类与猜数字游戏
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/14048764.html
Copyright © 2011-2022 走看看