zoukankan      html  css  js  c++  java
  • 前缀和+贪心+线段树——cf893D

    /*
    贪心策略:
        如果检查的那天不用加,那就不加
        反之加上尽可能多的钱
            如何确定这个值?
                处理出前缀和,第i天可以加的钱=d-[i+1,n]天里前缀和的最大值
            加上这个值后,要再一次更新前缀和数组,用线段树维护前缀和数组即可      
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 200005
    
    ll n,d,a[N],sum[N];
    vector<int>v;
    
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    ll lazy[N<<2],Max[N<<2];
    void pushdown(int rt){
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        Max[rt<<1]+=lazy[rt];
        Max[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
    void build(int l,int r,int rt){
        if(l==r){Max[rt]=sum[l];return;}
        int m=l+r>>1;
        build(lson);build(rson);
        Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); 
    } 
    void update(int L,int R,int v,int l,int r,int rt){
        if(L<=l && R>=r){
            Max[rt]+=v;lazy[rt]+=v;return;
        }
        pushdown(rt);
        int m=l+r>>1;
        if(L<=m)update(L,R,v,lson);
        if(R>m)update(L,R,v,rson);
        Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); 
    }
    ll query(int L,int R,int l,int r,int rt){
        if(L<=l && R>=r)return Max[rt];
        int m=l+r>>1;
        pushdown(rt);
        ll res=-0x3f3f3f3f3f3f3f3f;
        if(L<=m)res=max(res,query(L,R,lson));
        if(R>m)res=max(res,query(L,R,rson));
        return res;
    }
    int main(){
        cin>>n>>d;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++){
            sum[i]=sum[i-1]+a[i];
            if(sum[i]>d){
                cout<<-1;return 0;
            }
        }
        build(1,n,1);
        for(int i=1;i<=n;i++)
            if(a[i]==0)v.push_back(i);
        
        int ans=0;
        for(auto pos:v){
            ll cur=query(pos,pos,1,n,1);
            if(cur>=0)continue;
            ans++;
            ll mx=query(pos,n,1,n,1);
            ll dif=d-mx;
            if(dif+cur<0){
                cout<<-1<<'
    ';return 0;
            }
            update(pos+1,n,dif,1,n,1);
        }
        
        cout<<ans<<'
    ';
        
    }
  • 相关阅读:
    Reverse Nodes in k-Group [LeetCode]
    Text Justification [LeetCode]
    Path Sum [LeetCode]
    Multiply Strings [LeetCode]
    Populating Next Right Pointers in Each Node II [Leetcode]
    013 集合
    012 元组
    02 isdecimal(), isdigit(), isnumeric()
    011 字符串的内置方法 三
    010 字符串的内置方法 二
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12296666.html
Copyright © 2011-2022 走看看