1. 程式人生 > >codeforces 878C Tournament平衡樹,好題!!!!

codeforces 878C Tournament平衡樹,好題!!!!

C. Tournament time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

Recently a tournament in k kinds of sports has begun in Berland. Vasya wants to make money on the bets.

The scheme of the tournament is very mysterious and not fully disclosed. Competitions are held back to back, each of them involves two sportsmen who have not left the tournament yet. Each match can be held in any of the k

 kinds of sport. Loser leaves the tournament. The last remaining sportsman becomes the winner. Apart of this, the scheme can be arbitrary, it is not disclosed in advance.

Vasya knows powers of sportsmen in each kind of sport. He believes that the sportsmen with higher power always wins.

The tournament is held every year, and each year one new participant joins it. In the first tournament, only one sportsman has participated, in the second there were two sportsmen, and so on. Vasya has been watching the tournament for the last n

 years. Help him to find the number of possible winners for each of the n tournaments.

Input

The first line contains two integers n and k (1 ≤ n ≤ 5·1041 ≤ k ≤ 10) — the number of tournaments and the number of kinds of sport, respectively.

Each of the next n lines contains k integers si1, si2

, ..., sik (1 ≤ sij ≤ 109), where sij is the power of the i-th sportsman in the j-th kind of sport. The sportsman with higher powers always wins. It's guaranteed that for any kind of sport all of these powers are distinct.

Output

For each of the n tournaments output the number of contenders who can win.

Examples input
3 2
1 5
5 1
10 10
output
1
2
1
input
3 2
2 2
3 3
1 10
output
1
1
3
input
3 2
2 3
1 1
3 2
output
1
1
2
Note

In the first sample:

In the first tournament there is only one sportsman, and he is the winner.

In the second tournament, there are two sportsmen, and everyone can defeat another, depending on kind of sports.

In the third tournament, the third sportsman in the strongest in both kinds of sports, so he is the winner regardless of the scheme.

題解:

感覺這是一道非常好的題目。

每個人看成一個k維的向量,對於任意兩個向量,依次考慮每一個維度,並且由較大的向量向較小的向量建立邊。這樣的話,就形成了一副圖。

對圖進行強連通分量的分解,強連通分量內的任意一個元素都可以成為分量內的winner。整個圖化成了DAG,並且這個DAG中,入度為0的點(或強聯通分量)只能有一個。

(解釋:這樣想,假設有兩個入度為0的點,由我們建圖的方式可以知道他們之間必然存在著有向邊,矛盾)

所以這個入度為0的點(或強聯通分量)裡面包含的元素個數就都是答案。

然而每次都建圖,求scc顯然是不現實的,因此我們需要一個數據結構來維護DAG。

我們定義一個node結構體,表示一個組,組相當於scc。

組內的元素都可以成為該組的winner,每個組儲存2個向量(小向量和大向量),其中小向量分量表示組中所有向量的該分量的最小值,大向量表示的東西恰好相反。

維護DAG可以用平衡樹,過載<運算子,即node1<node2當且僅當node1大向量嚴格<node2的小向量:

bool operator<(const node &nd)const{
	for(int i = 0;i < k;++i){
		if(M[i] > nd.m[i]) return false;
	}
	return true;
}
每遇到一個新的node要插入時

lower_bound會找到第一個嚴格 < node的後面一個的位置lb

upper_bound會找到第一個嚴格> node的位置ub

lb 和 ub之間的 (不包含ub)任何元素都可以與新的node建立雙向邊的關係從而構成新的聯通分量,所以把他們取出來合併到一起再丟回去。

程式碼:

#include <bits/stdc++.h>
using namespace std;
int n,k;
struct node{
	int sz;
	vector<int> m,M;
	node(){
		sz = 1;
		for(int i = 0;i < k;++i){
			int tmp;scanf("%d",&tmp);
			m.push_back(tmp);
			M.push_back(tmp);
		}
	}
	bool operator<(const node &nd)const{
		for(int i = 0;i < k;++i){
			if(M[i] > nd.m[i]) return false;
		}
		return true;
	}
	void merge(const node &nd){
		for(int i = 0;i < k;++i){
			m[i] = min(m[i],nd.m[i]);
			M[i] = max(M[i],nd.M[i]);
		}
		sz += nd.sz;
	}
};
set<node> st;
int main(){
	scanf("%d%d",&n,&k);
	for(int i = 0;i < n;++i){
		node nd = node();
		auto lb = st.lower_bound(nd),ub = st.upper_bound(nd);
		while(lb!= ub){
			nd.merge(*lb);
			lb = st.erase(lb);
		}
		st.insert(nd);
		printf("%d\n",(st.rbegin())->sz);
	}
	return 0;
}