有 N 個評估小組,每組成員位置構成等差數列:S, S+D, S+2D, ..., S+KD ≤ E。
若某位置有奇數個成員,秦騰可突圍。已知全路徑上最多只有一個這樣的位置。求該位置及人數,或輸出 "Poor QIN Teng:("。
約束:N ≤ 200000,坐標 ≤2^31-1,總人數 ≤10^8。
f(x) = [0, x] 區間內總人數 是單調遞增的。f(x) 為奇數,則唯一的奇數點必在 [0, x] 內;若為偶數,則在 (x, MAX]。f(x) 為奇數的 x,即為目標位置。(S_i, E_i, D_i),記錄最大坐標 MAX = max(E_i)。l=0, r=MAX:
mid = (l+r)/2cnt = Σ max(0, (min(E_i,mid)-S_i)/D_i + 1) (S_i ≤ mid 才計數)cnt % 2 == 1 → r = mid;否則 l = mid+1。ans = l。ans 處成員數 c = Σ [S_i ≤ ans ≤ E_i && (ans-S_i)%D_i==0]。
c 為奇數 → 輸出 ans c。#includeusing namespace std; typedef long long LL; const LL INF = 2147483647; const int MAXN = 200005; LL S[MAXN], E[MAXN], D[MAXN]; int T, N; bool check(LL x) { LL cnt = 0; for (int i=1; i<=N; ++i) if (S[i] <= x) { if (E[i] <= x) cnt += (E[i] - S[i]) / D[i] + 1; else cnt += (x - S[i]) / D[i] + 1; } return cnt & 1; } LL binary_search(LL l, LL r) { if (l == r) return l; LL mid = (l + r) >> 1; return check(mid) ? binary_search(l, mid) : binary_search(mid+1, r); } int main() { scanf("%d", &T); while (T--) { scanf("%d", &N); LL MAX = 0; for (int i=1; i<=N; ++i) { scanf("%lld%lld%lld", &S[i], &E[i], &D[i]); if (E[i] > MAX) MAX = E[i]; } LL ans = binary_search(0, MAX); LL cnt = 0; for (int i=1; i<=N; ++i) if (S[i] <= ans && ans <= E[i] && (ans - S[i]) % D[i] == 0) ++cnt; if (cnt & 1) printf("%lld %lld\n", ans, cnt); else puts("Poor QIN Teng:("); } return 0; }
check O(N),二分 O(log MAX) ≈ 31 次。O(N log MAX),N=2e5 極快。long long 防溢出。「最多一個奇數點」是關鍵提示,將問題轉化為單調謂詞上的二分。類似思想適用於「找唯一滿足條件的位置」、「中位數查找」等問題。