http://codeforces.com/problemset/problem/425/A
题意:给你n个数,给你k(n<=200,k<=10)
让你至多交换k对数,使得该序列的最大连续区间和最大
思路:
n比较小,直接枚举这个最大连续区间和的两端i,j。 (n^2)
对于每次枚举,我直接把i到j的元素丢到multiset,然后把两边剩余的求到优先队列里,做k次,每次从multiset取最小的,从优先队列取最大的,如果优先队列里取的最大值比set里的最小值大,就可以交换,以得到更大值,否则break
(注意容器为空的时候就不要取了,否则RE)
每次枚举更新答案即可
复杂度n^2(nlogn+klogn)。。。勉勉强强过得去吧
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
int tm[205];
multiset<int> ans;
priority_queue<int> sb;
multiset<int>::iterator it;
int main()
{
int n,m;
cin>>n>>m;
int i,j,k;
for (i=1;i<=n;i++)
scanf("%d",&tm[i]);
int ans_max=-1000*205;
for (i=1;i<=n;i++)
{
for (j=i;j<=n;j++)
{
while(!sb.empty()) sb.pop();
ans.clear();
for (k=i;k<=j;k++)
ans.insert(tm[k]);
for (k=1;k<i;k++)
sb.push(tm[k]);
for (k=j+1;k<=n;k++)
sb.push(tm[k]);
int tmp=m;
while(tmp--)
{
if (!sb.empty())
{
int minn=*ans.begin();
int maxx=sb.top();
if (maxx>minn)
{
sb.pop();
ans.erase(ans.find(minn));
ans.insert(maxx);
sb.push(minn);
}
else
break;
}
}
int cun=0;
for(it=ans.begin();it!=ans.end();it++)
cun+=*it;
if (cun>ans_max)
ans_max=cun;
}
}
printf("%d\n",ans_max);
return 0;
}

本文介绍了一种通过枚举技巧解决特定序列优化问题的方法,重点在于利用多集和优先队列进行元素交换,以达到序列最大连续区间和最大化的目的。通过详细步骤和复杂度分析,展示了该算法的实现过程及性能考量。
1455

被折叠的 条评论
为什么被折叠?



