#include using namespace std; using int64 = long long; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n; if(!(cin >> n)) return 0; vector w(n); for(int i=0;i> w[i]; int m; cin >> m; vector s(m); for(int i=0;i> s[i]; // マージして (bitW, bitS, len) のセグメント列を逐次生成して処理する int iw = 0, is = 0; int64 remW = (n>0 ? w[0] : 0); int64 remS = (m>0 ? s[0] : 0); auto bit_of_index = [](int idx)->int { return (idx % 2 == 0) ? 1 : 0; }; // 0-based index: 0 -> w1 -> ones int64 answer = 0; // 現在のブロックの DP。started=false の間はブロック未開始(直前に (0,0) があった状態) bool started = false; // dpK_score: 現在「末尾がK」であるときの最大スコア(ブロック内のみ含む) // dpK_len: 末尾の連続忘れ K の長さ(スコアには既に含まれている) int64 dpK_score = 0, dpK_len = 0; int64 dpT_score = 0, dpT_len = 0; auto flush_block = [&](){ if(!started) return; answer += max(dpK_score, dpT_score); started = false; dpK_score = dpK_len = dpT_score = dpT_len = 0; }; while(iw < n && is < m){ int bitW = bit_of_index(iw); int bitS = bit_of_index(is); int64 take = min(remW, remS); remW -= take; remS -= take; if(remW == 0){ iw++; if(iw < n) remW = w[iw]; } if(remS == 0){ is++; if(is < m) remS = s[is]; } // このセグメント (bitW,bitS,take) を処理 if(bitW == 0 && bitS == 0){ // セパレータ:ブロック終了 flush_block(); continue; } // ブロック内セグメントとして扱う if(!started){ // ブロック開始時の初期化 started = true; if(bitW==1 && bitS==0){ // forced K dpK_score = take * take; dpK_len = take; dpT_score = 0; dpT_len = 0; // impossible // but keep dpT_score small so max works } else if(bitW==0 && bitS==1){ dpT_score = take * take; dpT_len = take; dpK_score = 0; dpK_len = 0; } else { // bitW==1 && bitS==1 -> flexible // at block start we can choose either K or T for this flexible seg. dpK_score = take * take; dpK_len = take; dpT_score = take * take; dpT_len = take; } continue; } // 一般遷移 if(bitW==1 && bitS==0){ // forced K: T は impossible after this seg (cannot assign this seg to T) // new K can be extending previous K or starting new from previous T int64 cand_extendK = dpK_score + (2*dpK_len*take + take*take); // extend K run int64 cand_fromT = dpT_score + (take*take); // switch from T -> start new K run // It's possible dpK_score was 0 (if never had K before) but that's fine. if(dpK_len==0 && dpK_score==0 && dpT_len==0 && dpT_score==0){ // shouldn't happen because started==true } if(cand_extendK >= cand_fromT){ dpK_score = cand_extendK; dpK_len = dpK_len + take; } else { dpK_score = cand_fromT; dpK_len = take; } // dpT becomes impossible for now dpT_score = 0; dpT_len = 0; } else if(bitW==0 && bitS==1){ // forced T int64 cand_extendT = dpT_score + (2*dpT_len*take + take*take); int64 cand_fromK = dpK_score + (take*take); if(cand_extendT >= cand_fromK){ dpT_score = cand_extendT; dpT_len = dpT_len + take; } else { dpT_score = cand_fromK; dpT_len = take; } dpK_score = 0; dpK_len = 0; } else { // flexible (1,1): we may assign whole segment to K or to T. // compute newK by either extending K or starting new from T; similarly for newT. int64 newK_score1 = dpK_score + (2*dpK_len*take + take*take); // extend K int64 newK_score2 = dpT_score + (take*take); // switch from T -> start K int64 newK_score = max(newK_score1, newK_score2); int64 newK_len = (newK_score1 >= newK_score2) ? (dpK_len + take) : take; int64 newT_score1 = dpT_score + (2*dpT_len*take + take*take); // extend T int64 newT_score2 = dpK_score + (take*take); // switch from K -> start T int64 newT_score = max(newT_score1, newT_score2); int64 newT_len = (newT_score1 >= newT_score2) ? (dpT_len + take) : take; dpK_score = newK_score; dpK_len = newK_len; dpT_score = newT_score; dpT_len = newT_len; } } // 最後のブロックを確定 flush_block(); cout << answer << "\n"; return 0; }