//適度にばらついて移動することを期待した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]; const ll Kmax = 600; const ll center = 300; 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 = 0; 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]); 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][0] + A[i][1]); if(0 <= j - 1) nexdp[j - 1][0] = max(nexdp[j - 1][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++) ans = max(ans, dp[j][k]); } if(K2 * 2 == K) ans = max(ans, dp[center][0]); ans = max(ans, dp[center][1]); cout << ans << endl; } return 0; }