题目: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\n",ans);
return 0;
}