// algortithm_kickstart_2019D3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include <algorithm>
#include <queue>
//经计算发现,不管k为even or odd,都将中间节点归到左边:floor(k/2)+1;,两边可能相等,
//可能左边多一
//cost = leftsum(ci-xi)+rightsum(ci+xi)+(num_right-num_left)x_(floor(k/2)+1)
using namespace std;
typedef pair<int, int >pii;//first为量,后者为坐标
long long solve(vector<pair<int, int>> mat, int K, int N)
{
//init初始化部分
int k_1 = K / 2+1;//将中间节点加入到左边,不管k为odd or even
int k_2 = K - k_1 +1;
priority_queue<pii> q1;//大顶堆
priority_queue<pii, vector<pii>, greater<pii>> q2;//小根队
set<int> s;//有序集存储做标,便于替换,大小固定为(K-k1+1)
long long tmp=0, res=0;
for (int i = 0; i < k_1; i++)//左>=右
{
q1.push(make_pair(mat[i].second - mat[i].first, i));
tmp += mat[i].second - mat[i].first;
}
for (int i = N-1; i >= k_1 ; i--)
{
q2.push(make_pair(mat[i].first + mat[i].second,i));
}
for (int i = 0; i < k_2; i++)//取出最小的一半的下标
{
pair<int, int > tp=q2.top();
tmp += tp.first;
s.insert(tp.second);
q2.pop();
}
//迭代部分
res = tmp + (k_1 - k_2)*mat[k_1 - 1].first;
for (int i = k_1; i <(N - k_2); i++)//
{
if (!q1.empty() and mat[i].second - mat[i].first < q1.top().first)//更新左边
{
tmp -= q1.top().first;
//tmp -= (k_1 - k_2)*mat[i - 1].first;//还要减去上一个中心点的x,但不能是i-1,你不能确定,就是前一个更新了
q1.pop();
tmp += mat[i].second - mat[i].first;
q1.push(make_pair(mat[i].second - mat[i].first,i));
}
//更新右边
if (*s.begin() == i)//右边第一个点刚好是i
{
tmp -= mat[i].first + mat[i].second;
s.erase(i);//擦掉一个就要加上一个
pii d;
do
{
d = q2.top();
q2.pop();
} while (d.second <= i);
tmp += d.first;
s.insert(d.second);
}
//tmp=tmp + (k_1 - k_2)*mat[i].first;//这个中心点的x不能随便加进去了,由于以后还得减,所以不放进结果
//else//去掉堆中小于i的点
res = min(res, tmp+(k_1-k_2)*mat[i].first);//这个地方错误基本难以避免
}
return res;
}
int main()
{
//set<int > se{1,2};//若不等,则需擦掉所以比第一个坐标小的点,
//但不着急,无法得到,待到相等时再擦
//se.insert(0);
int T = 0;
cin >> T;
for (int t = 0; t < T; t++)
{
int K = 0, N = 0;
cin >> K >> N;
vector<pair<int, int>> mat(N,make_pair(0,0));//first 为x,second为c
for (int i = 0; i < N; i++)
{
cin >> mat[i].first;
}
for (int i = 0; i < N; i++)
{
cin >> mat[i].second;
}
sort(mat.begin(), mat.end(), [](pair<int, int> a, pair<int, int> b) {return a.first < b.first; });
long long y=solve(mat, K, N);//仓库看作特殊店铺处理
cout << "Case #" << t + 1 << ": " << y << endl;
}
//std::cout << "Hello World!\n";
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门提示:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
浙公网安备 33010602011771号