有 n 個房間排成一個環,編號分別是 0 到 n−1。
房間之間有單向的路徑,編號 i 的房間可以走到編號 (i+1) mod n 的房間。
每次進入編號 i 的房間可以獲得 pi 個點數(最一開始待的房間也可以獲得點數)。
現在依序有 m 個任務,第 i 個任務需要蒐集到 qi 個點數。對於每次的任務,若一開始在編號 s 的房間,且走到編號 t 的房間時候可以蒐集到需要的點數,則完成這次任務後會停在編號 (t+1) mod n 的房間。
一開始在編號 0 的房間,依據接收到 m 個任務,請求出完成第 m 個任務後會停在哪個編號的房間?
範例測資
範例輸入 | 範例輸出 |
---|---|
第一行包含兩個正整數 N 和 M (1 <= N <= 200000、1 <= M <= 20000)。 第二行包含 N 個正整數 Pi,P 的總和不超過 109。 第三行包含 M 個正整數 Qi,Qi 不會超過 P 的總和。 | 輸出一個非負整數表示最後停在哪個編號的房間。 |
7 3 2 1 5 4 3 5 3 8 9 12 | 4 |
4 3 1 3 5 7 4 2 2 | 0 |
解題思路
使用二分搜尋,只是目標改成 Qi + 目前位置的前綴和,並且要將結果 % N。如果目標大於最大的前綴和 (最後一個數字),則將目標 -= 最大前綴和。最後輸出最終位置即可。
範例程式碼-ZeroJudge F581: 圓環出口
#include <iostream>
using namespace std;
int N, M, num[200000] = {}, prefix[200000] = {};
int binary(const int L, const int R, const int target) {
if (L >= R) return R;
const int middle = (L+R)/2;
if (target > prefix[middle]) {
return binary(middle+1, R, target);
}
return binary(L, middle, target);
}
int main() {
cin.sync_with_stdio(0);
cin.tie(0);
cin >> N >> M;
int sum = 0;
prefix[0] = 0;
for (int i = 0; i<N; i++) {
cin >> num[i];
sum += num[i];
prefix[i+1] = sum;
}
int position = 0;
for (int i = 0; i<M; i++) {
int Q;
cin >> Q;
int target = Q+prefix[position];
if (target > prefix[N]) target -= prefix[N];
position = binary(0, N, target) % N;
}
cout << position << "\n";
}
//ZeroJudge F581
//Dr. SeanXD