//貪欲+適度にばらついて移動することを期待したDP(嘘解法) //移動が1か所にまとまるコーナーケース回避 //制限時間に間に合うよう調整 #include #include #include using namespace std; using namespace atcoder; using ll = long long; const long long INF = 1000000000000000000; //#define endl "\n"; ll Q, N, K, A[200009][2]; ll solve1(){ const ll Kmax = 200; const ll buff = 100; ll ret = -INF; vector> vb; ll pos = 0, left = 0, valA = 0, valB = 0; vector chg(N, 0); for(int i = 0; i < N; i++){ if(pos == 0){ if(A[i][0] < A[i][1]){ pos = 1; valA = A[i][1]; valB = A[i][0]; left = i; continue; } } if(pos == 1){ if(A[i][0] > A[i][1]){ pos = 0; vb.push_back(make_tuple(valA - valB, left, i)); valA = 0; valB = 0; continue; }else{ valA += A[i][1]; valB += A[i][0]; } } } if(valA - valB > 0) vb.push_back(make_tuple(valA - valB, left, N)); sort(vb.rbegin(), vb.rend()); ll selected = 0, posvb = 0; ll K2 = (K + 1) / 2; while(selected <= K2 - buff && posvb < (int)vb.size()){ auto [val, l, r] = vb[posvb]; chg[l] = 1; selected++; posvb++; } if(selected <= K2 - buff){ //全部選べる ll ret = 0; for(int i = 0; i < N; i++){ if(A[i][0] >= A[i][1]){ ret += A[i][0]; }else{ ret += A[i][1]; } } return ret; } vector> dp(Kmax + 1, vector(2,-INF)); vector> nexdp(Kmax + 1, vector(2,-INF)); dp[K2 - selected][0] = 0; for(int i = 0; i < N; i++){ for(int j = 0; j <= Kmax; j++){ for(int k = 0; k < 2; k++){ if(chg[i] == 0){ nexdp[j][0] = max(nexdp[j][0], dp[j][0] + A[i][0]); nexdp[j][1] = max(nexdp[j][1], dp[j][1] + A[i][1]); if(0 <= j - 1) nexdp[j - 1][1] = max(nexdp[j - 1][1], dp[j][0] + A[i][1]); nexdp[j][0] = max(nexdp[j][0], dp[j][1] + A[i][0]); } if(chg[i] == 1){ if(j + 1 <= Kmax) nexdp[j + 1][0] = max(nexdp[j + 1][0], dp[j][0] + A[i][0]); //nexdp[j][1] = max(nexdp[j][1], dp[j][1] + A[i][1]); if(j + 1 <= Kmax) nexdp[j + 1][1] = max(nexdp[j + 1][1], dp[j][1] + A[i][1]); //なんで? nexdp[j][1] = max(nexdp[j][1], dp[j][0] + A[i][1]); nexdp[j][0] = max(nexdp[j][0], dp[j][1] + A[i][0]); } } } swap(dp, nexdp); } /*for(int j = 0; j <= min(K2, Kmax); j++) cout << dp[j][0] << " "; cout << endl; for(int j = 0; j <= min(K2, Kmax); j++) cout << dp[j][1] << " "; cout << endl;*/ for(int j = 0; j <= min(K2, Kmax); j++){ for(int k = 0; k < 2; k++) if(K2 * 2 - (j * 2 + k) <= K) ret = max(ret, dp[j][k]); } return ret; } ll solve2(){ const ll Kmax = 500; const ll center = 250; ll ret = -INF; vector> dp(Kmax + 1, vector(2,-INF)); vector> nexdp(Kmax + 1, vector(2,-INF)); ll K2 = (K + 1) / 2; dp[center][0] = 0; ll prehiku = 0; for(int i = 0; i < N; i++){ ll hiku = K2 * (i + 1) / N; for(int j = 0; j <= Kmax; j++){ if(prehiku == hiku){ nexdp[j][0] = max(nexdp[j][0], dp[j][0] + A[i][0]); nexdp[j][1] = max(nexdp[j][1], dp[j][1] + A[i][1]); if(j + 1 <= Kmax) nexdp[j + 1][1] = max(nexdp[j + 1][1], dp[j][0] + A[i][1]); nexdp[j][0] = max(nexdp[j][0], dp[j][1] + A[i][0]); }else{ //情報を1つ捨てる if(0 <= j - 1) nexdp[j - 1][0] = max(nexdp[j - 1][0], dp[j][0] + A[i][0]); nexdp[j][0] = max(nexdp[j][0], dp[j][0] + A[i][0]); //変更回数が増える分には構わない if(0 <= j - 1) nexdp[j - 1][1] = max(nexdp[j - 1][1], dp[j][1] + A[i][1]); nexdp[j][1] = max(nexdp[j][1], dp[j][1] + A[i][1]); //変更回数が増える分には構わない nexdp[j][1] = max(nexdp[j][1], dp[j][0] + A[i][1]); if(0 <= j - 1) nexdp[j - 1][0] = max(nexdp[j - 1][0], dp[j][1] + A[i][0]); nexdp[j][0] = max(nexdp[j][0], dp[j][1] + A[i][0]); //変更回数が増える分には構わない } } prehiku = hiku; swap(dp, nexdp); } for(int j = max(0LL, center - K2); j < center; j++){ for(int k = 0; k < 2; k++) ret = max(ret, dp[j][k]); } if(K2 * 2 == K) ret = max(ret, dp[center][0]); ret = max(ret, dp[center][1]); return ret; } int main(){ cin >> Q; for(int q = 1; q <= Q; q++){ cin >> N >> K; for(int i = 0; i < N; i++) cin >> A[i][0]; for(int i = 0; i < N; i++) cin >> A[i][1]; ll ans = -INF; ans = max(ans, solve1()); ans = max(ans, solve2()); cout << ans << endl; } return 0; }