题解:CF878C Tournament
更好的阅读体验
简单题。
我们只关心,假设现在已经维护出一个可能成为冠军的集合,在加入一个人后,情况会如何变化。
我们维护若干个集合,若只一个集合中的元素,集合内的所有元素均有可能成为冠军。
我们考虑一种偏序关系。对于集合
更进一步地,假设目前冠军集合
那么我们可以使用一个 std::set 来维护上述的集合,注意 set 中每一个元素都是一个集合,按上述的偏序关系排序。由于我们只关心偏序关系,我们只维护每个集合的最大值和最小值。
那么这道题就做完了。由于合并最多进行
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define N 50006
using namespace std;
int n,m;
struct Node{int sz,minn[12],maxn[12];}tmp;
bool operator <(Node x,Node y)
{
for(int i=1;i<=m;i++)if(x.maxn[i]>y.minn[i])return 0;
return 1;
}
Node operator +(Node x,Node y)
{
Node ret;ret.sz=x.sz+y.sz;
for(int i=1;i<=m;i++)
ret.maxn[i]=max(x.maxn[i],y.maxn[i]),ret.minn[i]=min(x.minn[i],y.minn[i]);
return ret;
}
set<Node> S;
main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
tmp.sz=1;
for(int j=1;j<=m;j++)
scanf("%lld",&tmp.maxn[j]),tmp.minn[j]=tmp.maxn[j];
set<Node>::iterator it;
while((it=S.find(tmp))!=S.end())tmp=tmp+*it,S.erase(it);
S.insert(tmp),printf("%lld\n",S.rbegin()->sz);
}
return 0;
}