【Tsinghua OJ】范圍查詢(Range)問題

【問題描述】
數(shù)軸上有n個點涛酗,對于任一閉區(qū)間 [a, b],試計算落在其內(nèi)的點數(shù)皱蹦。

【輸入】
第一行包括兩個整數(shù):點的總數(shù)n煤杀,查詢的次數(shù)m眷蜈。
第二行包含n個數(shù)沪哺,為各個點的坐標(biāo)。
以下m行酌儒,各包含兩個整數(shù):查詢區(qū)間的左辜妓、右邊界a和b。
【輸出】
對每次查詢,輸出落在閉區(qū)間[a, b]內(nèi)點的個數(shù)籍滴。
【輸入樣例】
5 2
1 3 7 9 11
4 6
7 12
【輸出樣例】
0
3
【限制】
0 ≤ n, m ≤ 5×105
對于次查詢的區(qū)間[a, b]酪夷,都有a ≤ b
各點的坐標(biāo)互異
各點的坐標(biāo)、查詢區(qū)間的邊界a孽惰、b晚岭,均為不超過10^7的非負(fù)整數(shù)
時間:2s,內(nèi)存:256MB


【solution】先不廢話勋功,先貼源代碼:<code><pre>
#include <stdio.h>
#include <stdlib.h> <br />
#define L 500005 <br />
int a[L]; <br />
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa) - (*pb);
} <br />
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
} <br />
int find(int begin, int end, int ac)
{
int mid, left = begin, right = end;
while (left <= right)
{
mid = left + ((right - left) >> 1);
if (a[mid] >= ac) right = mid - 1;
else left = mid + 1;
}
return left;
} <br />
int main()
{
int n, m, i;
scanf("%d %d\n", &n, &m); <br />
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
} <br />
qsort(a, n, sizeof(int), compare); <br />
for (i = 0; i < m; i++)
{
int l, r, ans, lf, rt;
scanf("%d %d", &l, &r); <br />
//make sure l <= r
if (l > r)
{
swap(l, r);
} <br />
rt = find(0, n - 1, r);
lf = find(0, n - 1, l);
ans = rt - lf;
if (a[rt] == r) ans++;
if (ans < 0) ans = 0; <br />
printf("%d\n", ans);
}
}</pre></code>
第一感覺都是這道題以前學(xué)的時候肯定做過坦报,很簡單,看到這個數(shù)據(jù)規(guī)目裥基本也就確定得用二分查找了片择。(反正看網(wǎng)上想先維護(hù)好線性數(shù)組再O(1)的查找是沒混過去的)

實際上,二分查找并沒有看起來那么簡單骚揍,尤其是具體寫起來的時候字管,有很多細(xì)節(jié)與臨界點的處理都得根據(jù)實際情況仔細(xì)斟酌。

結(jié)合上述源代碼信不,有幾點值得注意的地方:
1)qsort的用法嘲叔,參考了:http://www.cnblogs.com/CCBB/archive/2010/01/15/1648827.html。 Tsinghua OJ 不支持 algorithm 庫抽活。
2)倒數(shù)第三行代碼(if (a[rt] == r) ans++;)實際上就是二分查找結(jié)合具體情況對答案的調(diào)整借跪。不妨分上界和下界等于或者不等于a數(shù)組中的值分情況討論,即可明白這一行的涵義酌壕。這也跟二分查找?guī)讉€細(xì)節(jié)的處理相統(tǒng)一掏愁。
3)二分查找函數(shù)中這一行:mid = left + ((right - left) >> 1);。一方面卵牍,位運算提高運算效率果港;另一方面,不直接用 (left + right) >> 1 防止計算過程中數(shù)字越界糊昙,進(jìn)而導(dǎo)致數(shù)組下標(biāo)越界辛掠。
4)二分查找不要用遞歸形式。一是提高效率释牺;二是防止堆棧溢出萝衩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市没咙,隨后出現(xiàn)的幾起案子猩谊,更是在濱河造成了極大的恐慌,老刑警劉巖祭刚,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牌捷,死亡現(xiàn)場離奇詭異墙牌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)暗甥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門喜滨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人撤防,你說我怎么就攤上這事虽风。” “怎么了寄月?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵焰情,是天一觀的道長。 經(jīng)常有香客問我剥懒,道長内舟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任初橘,我火速辦了婚禮验游,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘保檐。我一直安慰自己耕蝉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布夜只。 她就那樣靜靜地躺著垒在,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扔亥。 梳的紋絲不亂的頭發(fā)上场躯,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機(jī)與錄音旅挤,去河邊找鬼踢关。 笑死,一個胖子當(dāng)著我的面吹牛粘茄,可吹牛的內(nèi)容都是我干的签舞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柒瓣,長吁一口氣:“原來是場噩夢啊……” “哼儒搭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芙贫,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤搂鲫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后屹培,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體默穴,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡怔檩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年褪秀,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓄诽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡媒吗,死狀恐怖仑氛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闸英,我是刑警寧澤锯岖,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站甫何,受9級特大地震影響出吹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辙喂,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一捶牢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巍耗,春花似錦秋麸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亲族,卻和暖如春炒考,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背霎迫。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工票腰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人女气。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓杏慰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親炼鞠。 傳聞我的和親對象是個殘疾皇子缘滥,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容