PKU 1065 Wooden Sticks

問題

n本の木の棒があり、それぞれの太さはw[i], 長さはl[i]である。
この木の棒を好きな順番で機械に入れていく。


最初の一本を入れるときには1のコストがかかる。
前の棒が(w[i], l[i])であるとき、次の棒(w'[i], l'[i])が
w[i]≦w'[i]かつl[i]≦l'[i]ならばコストがかからない。
そうでないならコストが1かかる。


適切な順序で棒を入れたとき、かかるコストの最小値を求めよ。

制約条件

n≦5000
w[i], l[i]≦10000

方針

DAGの最小パス被覆でやろうとしててTLEになってた。
二部グラフの最大マッチングの計算量はO(V(V + E))なので、どう考えても間に合わない。
(計算量をO(V^2)とかだと思ってた)


次のような貪欲法をすればいいとfura2さんのブログに書いてあった。


まず、wの昇順で棒を並べる。wが等しいときはlの昇順。
するとlだけを考えればいい。
lの今までにできた列の末尾を
l0 l1 l2 ...とすると、新しいlを列に加えるとき、
l≧liとなるようなliのうち最大のliをもつ列の末尾に加えればよい。


そのような列が存在しないとき、新しい列を作る。

ソースコード

int n;
pi p[5000];

int main()
{
	int cs;
	cin >> cs;
	while(cs--){
		
		map<int, int> m;
		cin >> n;
		rep(i, n) cin >> p[i].first >> p[i].second;
		
		sort(p, p + n);
		m[p[0].second]++;
		for(int i = 1; i < n; i++){
			map<int, int>::iterator it = m.upper_bound(p[i].second);
			it--;
			
			if(it ->first <= p[i].second){
				if(--it->second == 0) m.erase(it);
			}
			m[p[i].second]++;
		}
		cout << m.size() << endl;
	}
	return 0;
}