CodeForces 182C Optimal Sum

题目:http://codeforces.com/contest/182/problem/C

题意:让你求一个长度为len的区间的和的绝对值。但是你可以对数组中的数进行k次操作,每次可以将ai变为-ai。问最大的绝对值为多少。

可以用multiset来维护区间内最大的k个负数,同时维护s

然后将ai全部取反后再维护一遍

最后就可以得到最大值

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int a[N];
int main()
{
    int n,len;
    scanf("%d%d",&n,&len);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int k;
    scanf("%d",&k);
    ll ans=-1e18;
    for(int sign=0;sign<=1;sign++)
    {
        if (sign==1)
            for(int i=1;i<=n;i++)
                a[i]=-a[i];
        ll s=0;
        multiset<int> x,y;
        for(int i=1;i<=n;i++)
        {
            if (a[i]>=0)
                s+=a[i];
            else if (x.size()<k)
            {
                x.insert(a[i]);
                s+=-a[i];
            }
            else if (k!=0&&a[i]<*(--x.end()))
            {
                x.insert(a[i]);
                s+=-a[i];
                int v=*(--x.end());
                x.erase(x.find(v));
                y.insert(v);
                s-=-v;s+=v;
            }
            else
            {
                y.insert(a[i]);
                s+=a[i];
            }
            int j=i-len;
            if (j>=1)
            {
                if (a[j]>=0)
                    s-=a[j];
                else if (x.find(a[j])!=x.end())
                {
                    x.erase(x.find(a[j]));
                    s-=-a[j];
                    if (!y.empty())
                    {
                        int v=*(y.begin());
                        x.insert(v);
                        y.erase(y.find(v));
                        s-=v;s+=-v;
                    }
                }
                else
                {
                    y.erase(y.find(a[j]));
                    s-=a[j];
                }
            }

            if (j>=0)
                ans=max(ans,s);
        }
    }
    printf("%I64d
",ans);
    return 0;
}

  

原文地址:https://www.cnblogs.com/bk-201/p/8082589.html