题解:CF182C Optimal Sum

题目传送门

题目大意

有一个长度为 \(n\) 的数列 \(a\),可以对它进行最多 \(k\) 次操作,每次操作可以将一个数变为它的相反数,输出最后所有长度为 \(len\) 的数列的和的绝对值的最大值。

思路

根据贪心,我们发现对于一个长度为 \(len\) 的数列,要么把它的前 \(k\) 大正数变为相反数,要么把它的前 \(k\) 小负数变为相反数,这样保证最优。所以我们可以用 \(4\)multiset 分别维护当前在 \(len\) 区间内的前 \(k\) 大正数,区间内的其余正数,区间内的前 \(k\) 小负数,区间内的其余负数。

每次往后移动一位时,判断这一位数的正负,假定为正,那么把他与第一个 multiset 中的最小值比较,如果比它大,那么就把他加入第一个 multiset,否则加入第二个 multiset。否则,加入第二个。

删除同理,如果这个数原本在第一个 multiset 中,那么就把第二个 multiset 中的最大值加入第一个 multiset,否则直接从第二个 multiset 中删除即可。

注意删除前,一定要判断这个数是否在 multiset 中。

代码

#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;
}
posted @ 2025-09-07 21:46  一班的hoko  阅读(8)  评论(0)    收藏  举报