欲望以提升热忱,毅力以磨平高山!|

XichenOC

园龄:1个月粉丝:4关注:0

📂题解
🔖其他
2025-01-23 13:48阅读: 49评论: 0推荐: 0

CF2063B Subsequence Update

Subsequence Update

题目翻译:

给定一个序列。在给定一个区间 \([l,r]\),你可以任意选择几个数,使所选的所有数左右颠倒。求如何颠倒才能使区间内的所有数之和最小。

思路:

若要使整个区间内所有数和最少,那一定就使尽量小的数翻转到区间内。我们发现我们只需要在区间左边或右边选择几个数,在在区间内选等量的数,翻转之后,所选的数就进去了。因此我们可以根据该性质。就可以发现,我们只需要在区间左边或右边选择较小的数与区间内较大的数替换即可。

实现:

可以建两个小根堆,分别储存区间加区间左边和区间加区间右边。然后只需要在两个小根堆中选择区间长度个数,在取最小值即可。这样所选择的就是最少答案。

完整代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int a[N];
priority_queue<int,vector<int>,greater<int>>q1,q2;
signed main(){
    int t;
    scanf("%lld",&t);
    while(t--){
        int n,l,r;
        scanf("%lld%lld%lld",&n,&l,&r);
        int len=r-l+1;
        while(!q1.empty())q1.pop();
        while(!q2.empty())q2.pop();
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            if(i<=r){
                q1.push(a[i]);
            }
            if(i>=l){
                q2.push(a[i]);
            }
        }
        int sum1=0,sum2=0;
        for(int i=1;i<=len;i++){
            sum1+=q1.top();
            sum2+=q2.top();
            q1.pop();
            q2.pop();
        }
        cout<<min(sum1,sum2)<<endl;
    }
}

本文作者:XichenOC

本文链接:https://www.cnblogs.com/XichenOC/p/18687668

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   XichenOC  阅读(49)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起