团体程序设计天梯赛(L3-017 森森快递 (30 分))

题目:

思路分析:

结合贪心的想法(区间覆盖问题 就是让右端点从小到大排序就行

就是一个区间查询最小值问题 然后每次查询减去对应区间的最小值(线段树就行

代码实现:

/*
*@Author:   GuoJinlong
*@Language: C++
*/
//#include <bits/stdc++.h>
/*
 *                                                     __----~~~~~~~~~~~------___
 *                                    .  .   ~~//====......          __--~ ~~
 *                    -.            \_|//     |||\\  ~~~~~~::::... /~
 *                 ___-==_       _-~o~  \/    |||  \\            _/~~-
 *         __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
 *     _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
 *   .~       .~       |   \\ -_    /  /-   /   ||      \   /
 *  /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
 *  |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
 *           '         ~-|      /|    |-~\~~       __--~~
 *                       |-~~-_/ |    |   ~\_   _-~            /\
 *                            /  \     \__   \/~                \__
 *                        _--~ _/ | .-~~____--~-/                  ~~==.
 *                       ((->/~   '.|||' -_|    ~~-/ ,              . _||
 *                                  -_     ~\      ~~---l__i__i__i--~~_/
 *                                  _-~-__   ~)  \--______________--~~
 *                                //.-~~~-~_--~- |-------~~~~~~~~
 *                                       //.-~~~--\
 *                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *                               神兽保佑            永无BUG
 */


const int MAX=4e5+10;
struct node{
    int l,r;
}p[MAX];
int num[MAX];
int la[MAX];
int tree[MAX];
bool cmp(node a,node b){
    if(a.r==b.r){
        return a.l<b.l;
    }
    return a.r<b.r;
}
void pushdown(int i){
    if(la[i]==0) return;
    tree[i<<1]-=la[i];
    tree[i<<1|1]-=la[i];
    la[i<<1]+=la[i];
    la[i<<1|1]+=la[i];
    la[i]=0;
}
void built(int l,int r,int i){
    la[i]=0;
    if(l==r){
        tree[i]=num[l];
        return;
    }
    int mid=l+r>>1;
    built(l,mid,i<<1);
    built(mid+1,r,i<<1|1);
    tree[i]=min(tree[i<<1],tree[i<<1|1]);
}
void updata(int L,int R,int l,int r,int d,int i){
    if(l<=L&&R<=r){
        tree[i]-=d;
        la[i]+=d;
        return;
    }
    int mid=L+R>>1;
    pushdown(i);
    if(mid>=l){
        updata(L,mid,l,r,d,i<<1);
    }
    if(mid<r){
        updata(mid+1,R,l,r,d,i<<1|1);
    }
    tree[i]=min(tree[i<<1],tree[i<<1|1]);
}
ll  query(int L,int R,int l,int r,int i){
    if(l<=L&&R<=r){
        return tree[i];
    }
    int mid=L+R>>1;
    int ans=INF;
    pushdown(i);
    if(mid>=l){
        ans=min(ans,query(L,mid,l,r,i<<1));
    }
    if(mid<r){
        ans=min(ans,query(mid+1,R,l,r,i<<1|1));
    }
    return ans;
}
int main(){
    int m,n;
    cin>>m>>n;
    ll ans=0;
    for(int i=0;i<m-1;i++){
        cin>>num[i];
    }
    built(0,m-2, 1);
    for(int i=0;i<n;i++){
        cin>>p[i].l>>p[i].r;
        if(p[i].l>p[i].r){
            swap(p[i].l,p[i].r);
        }
        p[i].r--;
    }
    sort(p,p+n,cmp);
    for(int i=0;i<n;i++){
        ll cnt=query(0,m-2,p[i].l,p[i].r,1);
        ans+=cnt;
        updata(0,m-2,p[i].l,p[i].r,cnt,1);
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/m0_57006708/article/details/121276398