【題解】T6843 麥粒商店
阿新 • • 發佈:2019-01-04
原題連結
演算法分析
此題末尾的資料範圍很明顯告訴我們順序查詢是拿不了滿分的,而題目裡又保證了輸入的麥粒數為升序序列,這時使用二分查詢就能很好地提高效率。順序查詢的時間複雜度為O(n),而二分查詢的時間複雜度為O(log2n)。所謂二分查詢,就是每次取數列正中間的數與要查詢的數比較,如果比要查詢的數大,就繼續在左半邊查詢,反之則在右半邊查詢,查詢的方法仍像這樣,找到這個數就退出迴圈,因此二分查詢又稱作折半查詢,前提是查詢的序列為有序序列。本題則是兩次使用二分查詢每位顧客所需麥粒的左邊界和右邊界,最後用 右邊界 - 左邊界 求出每位顧客的麥粒總數。示例程式碼
#include <cstdio> int n, m, v[1000001], ans[1000001], x, y, l, r, first, last, mid, c = 1;//v陣列用來存現有的麥粒,ans陣列存答案 int main() { scanf ( "%d%d", &n, &m );//輸入n和m for ( int i = 1 ; i <= n ; i++ ) scanf ( "%d", &v[i] );//輸入現有麥粒 for ( int i = 1; i <= m; i++ )//n位顧客迴圈 { scanf ( "%d%d", &x, &y );//每次輸入麥粒範圍 l = 0 , r = n , y++; //l為最左邊,r為最右邊,都是陣列下標,為了使沒有查到剛好落在y的左邊,y需要+1 while ( l <= r )//第一次查詢左邊界 { mid = ( l + r ) >> 1;//mid為正中間的數,即(l+r)/2,這是位運算寫法 if ( v[mid] < x ) l = mid + 1 , first = mid;//查詢右半部分,first為左邊界 else r = mid - 1;//查詢右半部分 } l = 0 , r = n;//賦回原來的值 while ( l <= r )//第二次查詢右邊界 { mid = ( l + r ) >> 1;//取中值 if ( v[mid] < y ) l = mid + 1 , last = mid;//同理,last為右邊界 else r = mid - 1; } ans[c++] = last - first;//右邊界 - 左邊界,答案存進ans陣列 } for ( int i = 1; i < c; i++ ) printf ( "%d\n", ans[i] );//輸出答案 return 0; }