这题比赛的时候不会做,原来是区间暴力。
其实理解起来也觉得挺简单的,可能是看题的时候被交换这个思想束缚了自己的解题吧,所以一直想不出什么好的做法,看了别人的解题茅舍顿开……
解法:就是在这个数列中先选出一段我们要求的区间,如果在中间取的这段的话,那旁边两段就是剩余的段,也就是我们需要至少k次交换剩余段中最大的值与刚开始选出的段交换最小的值,然后求这选出的这段的和,如此下去更新最大值就得到结果了。选出的段为 [ i , j ],剩余的段就是:[ 0 , i - 1 ] 与 [ j+1 , n - 1 ]。
如此暴力更新下去复杂度为 O(n^2log2n),n<=200,k<=10,所以1秒是可以接受的了……神奇!
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset(a,b,sizeof(a)) #define sca(a) scanf("%d",&a) #define sc(a,b) scanf("%d%d",&a,&b) #define pri(a) printf("%d\n",a) #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define MM 1000005 #define MN 2005 #define INF 100004 #define eps 1e-7 using namespace std; typedef long long ll; int main() { int n,k,i,j,p,a[205],Max=-1000; sc(n,k); for(i=0;i<n;i++) sca(a[i]); for(i=0;i<n;i++) for(j=i;j<n;j++) { vector<int>u,v; for(p=0;p<n;p++) if(p<i||p>j) v.push_back(a[p]);//v是剩余的两边区间 else u.push_back(a[p]);//u是所求区间[i,j] sort(v.rbegin(),v.rend());//降序 for(p=0;p<k&&p<v.size();p++) //交换v区间中大的值给u区间 u.push_back(v[p]); sort(u.rbegin(),u.rend()); //降序排序后前j-i个就是所需的了,后u.size()-(j-i)个就是交换出的最小值了 int sum=0; for(p=0;p<=j-i;p++) sum+=u[p]; //相当于把大值与小值交换了 Max=max(Max,sum); } pri(Max); return 0; }
CF:Problem 425A - Sereja and Swaps 区间交换最大值,码迷,mamicode.com
CF:Problem 425A - Sereja and Swaps 区间交换最大值
原文地址:http://blog.csdn.net/u011466175/article/details/24725303