专栏文章

题解:CF182C Optimal Sum

CF182C题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miozt104
此快照首次捕获于
2025/12/03 03:50
3 个月前
此快照最后确认于
2025/12/03 03:50
3 个月前
查看原文

题目传送门

题目大意

有一个长度为 nn 的数列 aa,可以对它进行最多 kk 次操作,每次操作可以将一个数变为它的相反数,输出最后所有长度为 lenlen 的数列的和的绝对值的最大值。

思路

根据贪心,我们发现对于一个长度为 lenlen 的数列,要么把它的前 kk 大正数变为相反数,要么把它的前 kk 小负数变为相反数,这样保证最优。所以我们可以用 44multiset 分别维护当前在 lenlen 区间内的前 kk 大正数,区间内的其余正数,区间内的前 kk 小负数,区间内的其余负数。
每次往后移动一位时,判断这一位数的正负,假定为正,那么把他与第一个 multiset 中的最小值比较,如果比它大,那么就把他加入第一个 multiset,否则加入第二个 multiset。否则,加入第二个。
删除同理,如果这个数原本在第一个 multiset 中,那么就把第二个 multiset 中的最大值加入第一个 multiset,否则直接从第二个 multiset 中删除即可。
注意删除前,一定要判断这个数是否在 multiset 中。

代码

CPP
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1010101;
ll n,len,k,a[N],sum1,sum2,sum,ans;
multiset<ll>st1,st2,st3,st4;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>len;
    for(int i=1;i<=n;i++)cin>>a[i];
    cin>>k;
    for(int i=1;i<=n;i++){
        sum=sum+a[i]-a[max(i-len,0ll)];
        if(k==0){
        	if(i>=len)ans=max(ans,abs(sum));
        	continue;
		}
        if(a[i]>=0){
            if(st1.size()<k)st1.insert(-a[i]),sum1+=a[i];
            else{
                if(-a[i]<=*st1.rbegin()){
                    sum1+=a[i];
                    sum1+=*st1.rbegin();
                    st3.insert(*st1.rbegin());
                    st1.erase(--st1.end());
                    st1.insert(-a[i]);
                }
                else st3.insert(-a[i]);
            }
        }
        if(a[i]<0){
            if(st2.size()<k)st2.insert(a[i]),sum2+=a[i];
            else{
                if(a[i]<=*st2.rbegin()){
                    sum2+=a[i];
                    sum2-=*st2.rbegin();
                    st4.insert(*st2.rbegin());
                    st2.erase(--st2.end());
                    st2.insert(a[i]);
                }
                else st4.insert(a[i]);
            }
        }
        if(a[max(i-len,0ll)]>=0&&i>len){
            if(st1.find(-a[i-len])!=st1.end()){
                st1.erase(st1.find(-a[i-len]));
                st1.insert(*st3.begin());
                sum1-=a[i-len];
                sum1-=*st3.begin();
                if(st3.begin()!=st3.end())st3.erase(st3.begin());
            }
            else if(st3.find(-a[i-len])!=st3.end())st3.erase(st3.find(-a[i-len]));
        }
        if(a[max(i-len,0ll)]<0&&i>len){
            if(st2.find(a[i-len])!=st2.end()){
                st2.erase(st2.find(a[i-len]));
                st2.insert(*st4.begin());
                sum2-=a[i-len];
                sum2+=*st4.begin();
                if(st4.begin()!=st4.end())st4.erase(st4.begin());
            }
            else if(st4.find(a[i-len])!=st4.end())st4.erase(st4.find(a[i-len]));
        }
        if(i>=len)ans=max(ans,max(abs(sum-2*sum1),abs(sum-2*sum2)));
    }
    cout<<ans;
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...