# Divide and Conquer# Binary Search# Prefix Sum# Map

g277 - 3. 幸運數字

🔗 前往 ZeroJudge 原題

題目描述

題目要求在給定一個包含 n 個數字的陣列中,找到「幸運數字」。幸運數字的定義是通過遞迴地將陣列分割成左右兩個子陣列,並比較兩個子陣列的總和來確定。如果左邊的總和較小,則幸運數字在左邊的子陣列中,反之亦然。這個過程一直重複,直到只剩下一個數字,這個數字就是幸運數字。

解題思路

程式碼使用分治法來尋找幸運數字。首先,計算陣列的前綴和,並將每個數字及其索引儲存在 map 中,以便快速查找。然後,使用兩個指標 lr 來表示當前區間。在每次迭代中,程式碼在 map 中找到索引在 [l, r] 範圍內的數字,並計算左右子陣列的總和。根據總和的大小,更新 lr,縮小區間。這個過程一直重複,直到 lr 相等,此時 a[l] 就是幸運數字。

複雜度分析

  • 時間複雜度: O(n log n)
  • 空間複雜度: O(n)

程式碼

#include <iostream>
#include <map>
#include <set>
using namespace std;
long long l,r,n,a[300020],d[300020],it,rv,lv,tx;
map <long long,long long> mp;
map <long long,long long> :: iterator mit;
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	cin >> n;
	r=n-1;
	for(int i=0;i<n;++i){
		cin >> a[i];
		d[i+1]=d[i]+a[i];
		mp[a[i]]=i;
	}
	mit=mp.begin();
	while(l!=r){
		while(mit->second>r||mit->second<l){
			++mit;
		}
		it=mit->second;
		rv=d[r+1]-d[it+1];
		lv=d[it]-d[l];
		if(rv<lv){
			r=it-1;
		}
		else{
			l=it+1;
		}
	}
	cout << a[l];
}

Discussion