//貪欲マージテク+適度にばらついて移動することを期待したDP(嘘解法) //嘘解法の寄せ集め #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; } ll solve3(){ using classPQ = tuple; priority_queue, less> que; vector> tA(N + 1, vector(2, 0)); for(int i = 0; i < N; i++){ tA[i + 1][0] = A[i][0]; tA[i + 1][1] = A[i][1]; } tA[0][1] = -INF; vector l(N + 1, 0), r(N + 1, 0), tasu_a(N + 1, 0), tasu_b(N + 1, 0), selected(N + 1, 0); for(int i = 0; i <= N; i++){ l[i] = i, r[i] = i; if(tA[i][0] >= tA[i][1]){ tasu_a[i] = tA[i][0]; tasu_b[i] = tA[i][1]; selected[i] = 0; }else{ tasu_a[i] = tA[i][1]; tasu_b[i] = tA[i][0]; selected[i] = 1; } } ll pos = 0, chg = 0, ret = 0; dsu d(N + 1); for(ll i = 1; i <= N; i++){ if(tA[i][pos] < tA[i][(pos+1)%2]){ ll ld = d.leader(i - 1); ret += tasu_a[ld]; chg++; que.push(make_tuple(tasu_b[ld] - tasu_a[ld], ld, l[ld], r[ld], selected[ld])); pos = (pos+1)%2; }else{ ll ld1 = d.leader(i - 1); ll ld2 = d.leader(i); ll ld = d.merge(i - 1, i); tasu_a[ld] = tasu_a[ld1] + tasu_a[ld2]; tasu_b[ld] = tasu_b[ld1] + tasu_b[ld2]; l[ld] = min(l[ld1], l[ld2]); r[ld] = max(r[ld1], r[ld2]); selected[ld] = pos; d.merge(ld1, ld2); } } ll restId = d.leader(N); que.push(make_tuple(tasu_b[restId] - tasu_a[restId], restId, l[restId], r[restId], selected[restId])); ret += tasu_a[d.leader(N)]; while(!que.empty()){ auto [dd, tmpidx, tl, tr, sel] = que.top(); //cout << dd << " " << idx << " " << tl << " " << tr << " " << sel << " " << chg << endl; ll idx = d.leader(tmpidx); que.pop(); if(chg <= K) continue; //flip不要 if(tl != l[idx] || tr != r[idx]) continue; ll chgplus = 0; ll ld1 = d.leader(max(0LL, tl - 1)); ll ld2 = d.leader(min(N, tr + 1)); if(selected[idx] != selected[ld1]) chgplus++; if(selected[idx] != selected[ld2]) chgplus++; if(chgplus <= 0) continue; //入らないはず if(chg % 2 == K % 2 && chgplus == 1) continue; //もう1回余分にflipが必要になるのでやらない ret += dd; ll nextasu_a = tasu_b[idx], nextasu_b = tasu_a[idx]; ll nexld = idx; if(selected[idx] != selected[ld1]){ nextasu_a += tasu_a[ld1]; nextasu_b += tasu_b[ld1]; nexld = d.merge(idx, ld1); l[nexld] = min(l[idx], l[ld1]); r[nexld] = max(r[idx], r[ld1]); } if(selected[idx] != selected[ld2]){ nextasu_a += tasu_a[ld2]; nextasu_b += tasu_b[ld2]; nexld = d.merge(nexld, ld2); l[nexld] = min(l[nexld], l[ld2]); r[nexld] = max(r[nexld], r[ld2]); } selected[nexld] = (selected[idx] + 1) % 2; tasu_b[nexld] = nextasu_b; tasu_a[nexld] = nextasu_a; que.push(make_tuple(tasu_b[nexld] - tasu_a[nexld], nexld, l[nexld], r[nexld], selected[nexld])); chg -= chgplus; } 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()); ans = max(ans, solve3()); cout << ans << endl; } return 0; }