CF425A Sereja and Swaps(暴力枚举+贪心)题解

题意

给一个长为 \(n\) 的序列,以及交换次数 \(k\),每次可以在原先的序列 中任意交换两个数 交换后找一个最大子串和,输出其可能的最大值。 \(1 \leq n \leq 200; 1 \leq k \leq 10\)

算法

暴力枚举+贪心

思路(心路历程)

拿到题第一下还想这最大字段和DP什么的(雾),后来发现然而并不能消除后效性……

其实这题还是很良心的

暴力枚举每一段区间,考虑怎样交换能使答案最优,显然每次都要要用区间外的最大值来换区间内的最小值(前提条件是外最大值大于内最小值!),用堆维护最值即可。根本不用担心时间

复杂度

\(O(n^3 \log n)\).迷之复杂度

代码

#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

int n,k,a[210],ans;
priority_queue<int, vector<int>, greater<int> > q1,kk;
priority_queue<int, vector<int>, less<int> > q2,kkk;

int main(){
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++ i) scanf("%d", a + i);
    ans = -0x3f3f3f3f;
    for(int l = 1; l <= n; ++ l)
        for(int r = l; r <= n; ++ r){
            q1 = kk, q2 = kkk;
            int num = k, sum = 0;
            for(int i = 1; i <= n; ++ i){
                if(i >= l && i <= r) q1.push(a[i]);
                else q2.push(a[i]);
            }
            while(num -- && !q2.empty()){
                int top = q2.top(); q2.pop();
                int ttop = q1.top();
                if(ttop >= top) break;
                q1.pop(); q1.push(top);
            }
            while(!q1.empty()) sum += q1.top(), q1.pop();
            ans = max(ans, sum);
        }
    printf("%d\n", ans);
    return 0;
}
posted @ 2020-10-21 22:25  When_C  阅读(113)  评论(0编辑  收藏  举报