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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步