思路来源: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)。
use priority_queue:
use flag to save:
MY AC code:
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 int cmp(const int &a, const int &b){ 11 return a > b; 12 } 13 14 void work(int n, int m){ 15 for(int i = 1; i <= n; i++){ 16 scanf("%d", &num[i]); 17 sum[i] = sum[i-1] + num[i];//以 sum 数组记录 1 到 pos 的累计和 18 } 19 20 int ans = -1e8; 21 for(int i = 1; i <= n; i++){ 22 for(int j = i; j <= n; j++){ 23 int tmp = sum[j] - sum[i-1]; 24 int max_array[222], min_array[222]; 25 int max_flag, min_flag; 26 int max_sum = 0, min_sum = 0; 27 int MAX = -1e8, MIN = 1e8; 28 29 for(int k = i; k <= j; k++){ 30 min_array[min_sum++] = num[k]; 31 if(num[k] < MIN){ 32 MIN = num[k]; 33 min_flag = min_sum - 1; 34 } 35 } 36 for(int k = 1; k < i; k++){ 37 max_array[max_sum++] = num[k]; 38 if(num[k] > MAX){ 39 MAX = num[k]; 40 max_flag = max_sum - 1; 41 } 42 } 43 for(int k = j + 1; k <= n; k++){ 44 max_array[max_sum++] = num[k]; 45 if(num[k] > MAX){ 46 MAX = num[k]; 47 max_flag = max_sum - 1; 48 } 49 } 50 //m 次操作机会, 满足 Max 队列 和 Min 队列 非空, 并且Max 队列存在大于Min 队列最小元素 的元素 51 for(int k = 0; k < m && max_sum && min_sum && max_array[max_flag] > min_array[min_flag]; k++){ 52 tmp += max_array[max_flag] - min_array[min_flag]; 53 swap(max_array[max_flag], min_array[min_flag]); 54 int MAX = -1e8, MIN = 1e8; 55 for(int z = 0; z < min_sum; z++){ 56 if(min_array[z] < MIN){ 57 MIN = min_array[z]; 58 min_flag = z; 59 } 60 } 61 for(int z = 0; z < max_sum; z++){ 62 if(max_array[z] > MAX){ 63 MAX = max_array[z]; 64 max_flag = z; 65 } 66 } 67 } 68 ans = max(ans, tmp); 69 } 70 } 71 printf("%d ", ans); 72 } 73 74 int main(){ 75 int n, k; 76 while(EOF != scanf("%d%d", &n, &k)){ 77 work(n, k); 78 } 79 }
priority_queue:
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 ", ans); 41 } 42 43 int main(){ 44 int n, k; 45 while(EOF != scanf("%d%d", &n, &k)) 46 work(n, k); 47 }