Useful Skills
without algorithm & Datastrucure
Binary Search
二分搜索
當搜索的對象有單調性
對於一個問題 跟 一個序列
有這樣的性質時
Yes Yes Yes
Yes No
No No No No No No
就可以二分
How to?
找中間的點
mid = ( left + right ) / 2
Case 1
Yes
Yes Yes Yes Yes Yes
Yes
Yes No No No No
左邊的Yes都可以丟掉
left = mid;
Case 2
No
Yes Yes Yes No No
No
No No No No No
右邊的No都可以丟掉
right = mid;
Final
left right
...Yes Yes
Yes No
No No...
so...
while( right - left > 1)
背
while( r - l > 1)
{
int mid = (l + r) /2;
if(Yes) l = mid;
else r = mid;
}
left & right?
usually you can...
1 ~ n
left = 0;
right = n+1;
//maybe Wrong!
What can you search?
in
already
sort array
find a number x
if(array[mid] > x) right = mid;
else left = mid;
數值 最大化
數值 最小化
找極端值
所有單調的都可以二分
但是...
不見得會比較好
Special Case
二分答案
HOJ p003
離散化
程式不能表達連續的狀態
所以我們用 ( left , right)
描述一個區間
在一條直線上
有 N 個區間 (N<=100,000)
問你
被最多區間覆蓋
的區域
有多少區間
ex
1 ~ 5
2 ~ 7
6 ~ 8
3 ~ 4
1 2 3 4 5 6 7 8
o o o o o x x x
x o o o o o o x
x x x x x o o o
x x o o x x x x
1 2
3 3
2 2 2 1
用陣列記錄被覆蓋幾次
scanf( "%d %d" , &left, &right);
for(int i=left; i<=right ; i++)
array[i] ++;
100,000個區間 * 不知道多大的Range
=
TLE
1. 加入區間跟拔除區間
scanf("%d %d", &left ,&right);
array[ left ] ++;
array[ right
+1
] --;
int sum = 0;
for(int i=0 ; i<=N ; i++)
sum += array[i];
Sort Event
int t[100010];
int v[100010];
int pos[100010];
bool comp(int a,int b){
return t[a] < t[b];
}
Sort Event
for(int i=1;i<=N;i++)
pos[i] = i;
sort(pos+1, pos+N+1, comp);
Sort Event
int sum = 0;
for(int i=1;i<=N;i++)
sum += v[pos[i]];
Max Range : M
Max 區間數 : N
Array法 O(M)
Sort法 O(N log N)
離散化編號
Structure
struct RILAK {
int i, no;
int v;
}array[100];
Sort COMP
bool comp1(RILAK a, RILAK b){
return a.v < b.v;
}
//sort
Sort COMP
bool comp2(RILAK a, RILAK b)
{
return a.no < b.no;
}
//sort
Sort COMP
for(int i=1;i<=N;i++)
{
array[i].no = i;
}
Sort COMP
sort(array+1, array+N+1, comp1);
for(int i=1;i<=N;i++)
array[i].i = i;
sort(array+1, array+N+1, comp2);
Why?
get Rank!!!
for 區間資料結構
Thx
Made with Slides.com