// GPT-o3-mini-highによる生成コード #include using namespace std; typedef long long ll; // セグメントツリー用グローバル配列(各ラウンドごとに再構築します) vector seg, segMin, segMax, lazy; vector lazyFlag; // セグメントツリーを構築する関数 // idx: 現在のノード、[l, r] がその区間、A が初期配列 void buildTree(int idx, int l, int r, const vector& A) { if(l == r) { seg[idx] = A[l]; segMin[idx] = A[l]; segMax[idx] = A[l]; lazy[idx] = 0; // lazyFlag が false のときは値は使わない lazyFlag[idx] = false; return; } int mid = (l + r) / 2; buildTree(idx*2, l, mid, A); buildTree(idx*2+1, mid+1, r, A); seg[idx] = seg[idx*2] + seg[idx*2+1]; segMin[idx] = min(segMin[idx*2], segMin[idx*2+1]); segMax[idx] = max(segMax[idx*2], segMax[idx*2+1]); lazy[idx] = 0; lazyFlag[idx] = false; } // lazy 情報を子ノードへ伝搬 void pushDown(int idx, int l, int r) { if(lazyFlag[idx]) { int mid = (l + r) / 2; int left = idx*2, right = idx*2+1; // 左の子 seg[left] = lazy[idx] * (mid - l + 1); segMin[left] = lazy[idx]; segMax[left] = lazy[idx]; lazy[left] = lazy[idx]; lazyFlag[left] = true; // 右の子 seg[right] = lazy[idx] * (r - mid); segMin[right] = lazy[idx]; segMax[right] = lazy[idx]; lazy[right] = lazy[idx]; lazyFlag[right] = true; lazyFlag[idx] = false; } } // 区間 [ql,qr] に対して A[j] = max(A[j], X) を適用する void updateRange(int idx, int l, int r, int ql, int qr, ll X) { if(qr < l || r < ql) return; if(ql <= l && r <= qr) { // すでにすべての値が X 以上なら何もしない if(segMin[idx] >= X) return; // 全部 X 未満なら一括更新 if(segMax[idx] < X) { seg[idx] = X * (r - l + 1); segMin[idx] = X; segMax[idx] = X; lazy[idx] = X; lazyFlag[idx] = true; return; } } pushDown(idx, l, r); int mid = (l + r) / 2; updateRange(idx*2, l, mid, ql, qr, X); updateRange(idx*2+1, mid+1, r, ql, qr, X); seg[idx] = seg[idx*2] + seg[idx*2+1]; segMin[idx] = min(segMin[idx*2], segMin[idx*2+1]); segMax[idx] = max(segMax[idx*2], segMax[idx*2+1]); } // 区間 [ql,qr] の総和を返す ll queryRange(int idx, int l, int r, int ql, int qr) { if(qr < l || r < ql) return 0; if(ql <= l && r <= qr) return seg[idx]; pushDown(idx, l, r); int mid = (l + r) / 2; return queryRange(idx*2, l, mid, ql, qr) + queryRange(idx*2+1, mid+1, r, ql, qr); } // 更新クエリの構造体 struct UpdateQuery { int L, R; ll X; }; // 質問クエリ:区間 [L,R] の総和が初めて X 以上となる「更新回数」を求める struct Query { int L, R, id; ll X; int lo, hi; // 二分探索の区間。lo:未成立、hi:成立する候補(最小更新番号) }; // メイン int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, K, Q; cin >> N >> K >> Q; vector A(N); for (int i = 0; i < N; i++){ cin >> A[i]; } vector updates(K); for (int i = 0; i < K; i++){ int L, R; ll X; cin >> L >> R >> X; // 入力は 1-indexed なので 0-indexed に変換 updates[i].L = L - 1; updates[i].R = R - 1; updates[i].X = X; } // 初期状態の累積和を作成(質問クエリで初期状態で条件を満たすかチェック) vector prefix(N+1, 0); for (int i = 0; i < N; i++){ prefix[i+1] = prefix[i] + A[i]; } vector ans(Q, 0); vector active; for (int i = 0; i < Q; i++){ int L, R; ll X; cin >> L >> R >> X; L--; R--; ll initSum = prefix[R+1] - prefix[L]; if(initSum >= X) { ans[i] = 0; // 条件を初期状態で満たす } else { Query qu; qu.L = L; qu.R = R; qu.X = X; qu.id = i; qu.lo = 1; qu.hi = K + 1; // もし全更新後でも条件未達なら hi = K+1 として -1 と出力 active.push_back(qu); } } // セグメントツリー用配列のサイズを確保 int size = 4 * N + 10; seg.assign(size, 0); segMin.assign(size, 0); segMax.assign(size, 0); lazy.assign(size, 0); lazyFlag.assign(size, false); // 並列二分探索 (Parallel Binary Search) while(!active.empty()){ // 各質問について candidate = (lo+hi)/2 を求める vector> cand; // (candidate update数, active内でのインデックス) for (int i = 0; i < (int)active.size(); i++){ int mid = (active[i].lo + active[i].hi) / 2; cand.push_back({mid, i}); } sort(cand.begin(), cand.end()); // セグメントツリーを初期配列 A から構築 buildTree(1, 0, N-1, A); int cur = 0; // candidate の昇順に「更新クエリ」を適用しながら各質問の区間和を取得 for(auto &p : cand){ int target = p.first; // これだけ更新を適用した状態でチェック int qi = p.second; while(cur < target && cur < K) { UpdateQuery &up = updates[cur]; updateRange(1, 0, N-1, up.L, up.R, up.X); cur++; } ll s = queryRange(1, 0, N-1, active[qi].L, active[qi].R); if(s >= active[qi].X) active[qi].hi = target; else active[qi].lo = target + 1; } // 更新済みの質問で探索区間が収束したものは答えを確定する vector nextActive; for(auto &qu : active){ if(qu.lo == qu.hi){ if(qu.lo > K) ans[qu.id] = -1; else ans[qu.id] = qu.lo; } else { nextActive.push_back(qu); } } active.swap(nextActive); } for (int i = 0; i < Q; i++){ cout << ans[i] << "\n"; } return 0; }