Codeforces Round #243 (Div. 2) C. Sereja and Swaps

思路来源:http://blog.csdn.net/sf____/article/details/24626739

题目给出数据上限为200, 所以可以暴利所有区间。

解题思路:

for i in range(n):
  for j in range(n):
    create priority_queue
    for w in range(k):
      if(Max.top > Min.top)
        SWAP(Max[element], Min[element])

暴利枚举所有初始区间 [ i , j ] ,则剩下的区间为[ 1 ,  i - 1 ]和[ j + 1 , n
],

将选定区间的最小值与剩下区间的最大值交换,使选定区间的和越来越大。

非常好的暴力方法啊。复杂度(n^2)*(nlogn + k*logn)。

当然,这题目可以不用priority_queue

WA code:


#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

int num[222];
int sum[222];

bool cmp1(int a, int b){
return a > b;
}

void work(int n, int m){
for(int i = 1; i <= n; i++){
scanf("%d", &num[i]);
sum[i] = sum[i-1] + num[i];//以 sum 数组记录 1 到 pos 的累计和
}

int ans = -1e8;
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j++){
int tmp = sum[j] - sum[i-1];
int max_array[222], min_array[222];
int max_sum = 0, min_sum = 0;
int MAX = -1e8, MIN = 1e8;

for(int k = i; k <= j; k++)
min_array[min_sum++] = num[k];
sort(min_array, min_array + min_sum + 1);
for(int k = 1; k < i; k++)
max_array[max_sum++] = num[k];
for(int k = j + 1; k <= n; k++)
max_array[max_sum++] = num[k];
sort(max_array, max_array + max_sum + 1, cmp1);
//m 次操作机会, 满足 Max 队列 和 Min 队列 非空, 并且Max 队列存在大于Min 队列最小元素 的元素
for(int i = 0; i < m && max_sum && min_sum && max_array[0] > min_array[0]; i++){
tmp += max_array[max_sum] - min_array[min_sum];
swap(max_array[max_sum], min_array[min_sum]);
sort(min_array, min_array + min_sum + 1);
sort(max_array, max_array + max_sum + 1, cmp1);
}
ans = max(ans, tmp);
}
}
printf("%d\n", ans);
}

int main(){
int n, k;
while(EOF != scanf("%d%d", &n, &k))
work(n, k);
}


 1 #include <cstdio>
2 #include <cstring>
3 #include <queue>
4 #include <algorithm>
5 using namespace std;
6
7 int num[222];
8 int sum[222];
9
10 void work(int n, int m){
11 for(int i = 1; i <= n; i++){
12 scanf("%d", num+i);
13 sum[i] = sum[i-1] + num[i];//以 sum 数组记录 1 到 pos 的累计和
14 }
15
16 int ans = -1e8;
17 for(int i = 1; i <= n; i++){
18 for(int j = i; j <= n; j++){
19 int tmp = sum[j] - sum[i-1];
20
21 priority_queue<int> Max, Min;
22 for(int k = i; k <= j; k++)
23 Min.push(-num[k]);
24 for(int k = 1; k < i; k++)
25 Max.push(num[k]);
26 for(int k = j + 1; k <= n; k++)
27 Max.push(num[k]);
28
29 //m 次操作机会, 满足 Max 队列 和 Min 队列 非空, 并且Max 队列存在大于Min 队列最小元素 的元素
30 for(int i = 0; i < m && !Max.empty() && !Min.empty() && Max.top() + Min.top()>0; i++){
31 tmp += Max.top() + Min.top();
32 Max.push(-Min.top());
33 Min.push(-Max.top());
34 Max.pop();
35 Min.pop();
36 }
37 ans = max(ans, tmp);
38 }
39 }
40 printf("%d\n", ans);
41 }
42
43 int main(){
44 int n, k;
45 while(EOF != scanf("%d%d", &n, &k))
46 work(n, k);
47 }

Codeforces Round #243 (Div. 2) C. Sereja and Swaps,码迷,mamicode.com

时间: 2024-10-05 22:06:59

Codeforces Round #243 (Div. 2) C. Sereja and Swaps的相关文章

Codeforces Round #243 (Div. 2) C. Sereja and Swaps(优先队列 暴力)

题目 题意:求任意连续序列的最大值,这个连续序列可以和其他的 值交换k次,求最大值 思路:暴力枚举所有的连续序列.没做对是因为 首先没有认真读题,没看清交换,然后,以为是dp或者贪心 用了一下贪心,各种bug不对. 这次用了一下优先队列,以前用的不多,看这个博客又学了一下 AC代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #i

Codeforces Round #243 (Div. 2) A. Sereja and Mugs

#include <iostream> #include <vector> #include <algorithm> #include <numeric> using namespace std; int main(){ int n,s; cin >> n >> s; vector<int> a(n); for(int i = 0 ; i < n ; ++ i) cin >> a[i]; sort(a.b

Codeforces Round #243 (Div. 2) B. Sereja and Mirroring

#include <iostream> #include <vector> #include <algorithm> using namespace std; int main(){ int n,m; cin >> n >> m; vector<vector<int> > a(n,vector<int>(m,0)); for(int i = 0; i < n; ++ i){ for(int j = 0 ;

Codeforces Round #243 (Div. 1)——Sereja and Two Sequences

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

Codeforces Round #243 (Div. 1)

---恢复内容开始--- A 枚举l,r 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 us

Codeforces Round #243 (Div. 1) A题

http://codeforces.com/contest/425/problem/A 题目链接: 然后拿出这道题目是很多人不会分析题目,被题目吓坏了,其中包括我自己,想出复杂度,一下就出了啊!真是弱! 直接暴力求出矩阵数值,然后枚举每一个[I,J];再O[N]判断,分配好在[I,J]区间的数和之内的数,再排序下SOLO了 CODE:#include <cstdio> #include <cstring>#include <queue>#include <vect

Codeforces Round #243 (Div. 1)-A,B,C-D

这场CF真是逗了... 因为早上7点起的,所以到做CF的时候已经17个小时没有休息了,再加上中午5小时的比赛. 头脑很不清晰.做第一个题的时候差点读成求最大字段和了.然后发现是水体,迅速A掉. 然后开始看了B题,第一遍没有看懂,此时大脑已经看不下去了.然后突然某个群说D是水题. 我去看了一下D,我去,D的题意好简单啊....于是,冥思苦想中.....一直到快要1点 的时候,还是没有结果...此时我感觉不行了..要放弃D,于是,又去看B.仔细读了读题目, 才发现,B题才是真正的水题..一阵郁闷啊.

Codeforces Round #243 (Div. 2)——Sereja and Table

看这个问题之前,能够先看看这个论文<一类算法复合的方法>,说白了就是分类讨论,可是这个思想非常重要 题目链接 题意: 首先给出联通块的定义:对于相邻(上下和左右)的同样的数字视为一个联通块 现给一个n*m的仅仅有0和1的矩形和数字k,求出最小反转个数使得总体包含若干个矩形联通块(即每一个联通块均是矩形)(1?≤?n,?m?≤?100; 1?≤?k?≤?10) 假设最小次数比k大,输出-1 分析: 题目的特点是k比較小.也就是说反转的次数比較少,所以能够从这里入手.直接枚举全部的位置肯定是不行了

Codeforces Round #243 (Div. 1)——Sereja and Squares

题目链接 题意: 给n个点,求能组成的正方形的个数. 四边均平行与坐标轴 大神的分析: 经典题 我们考虑每一种x坐标,显然仅仅有<= sqrt{N}个x坐标出现了> sqrt{N}次,我们称这些为大的,其它为小的. 我们先考虑大的x和其它x之间的答案,先O(sqrt{N})枚举一个大的坐标,然后for其它的每一个点,这样能够依据x坐标的差算出正方形的边长,hash检查一下就能知道这个正方形是否存在. 之后考虑小的x和小的x之间的答案,注意到我们能够对每一个横坐标直接平方for,这样仅仅有(sq