Codeforces Round #443 (Div. 1) C. Tournament 思维题

本文介绍了一种竞赛预测算法,该算法通过分析参赛者在多种技能上的表现来预测潜在的胜者。每年新加入一名选手,算法需要计算出每届比赛中可能获胜的选手数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C. Tournament
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard 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·104, 1 ≤ 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
题意:每个人有k个属性,如果他其中有一个属性大于他的对手,那么他就有可能打败他的对手,每次比赛失败的人退场,问给出任意的出场顺序,问有多少个人有希望获得胜利,每一年会来一个新的选手,对于每一年输出这一年可能获胜的人。
做法:如果两个人你可以打败我,我也可以打败你,就可以把这两个人看做是一个集合,只要有人能打败这个集合的人,又会被这个集合的人打败,那么就把他们看成一个集合,每次输出最大集合的大小就好了。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
const int N = 5e4+100;
int n,k;
struct node{
    int sz;
    int mn[15],mx[15];
    void init(int a){
        sz = 0;
        for(int i= 1;i <= k;i++){
            mx[i] = mn[i] = a;
        }
    }
    void unit(node a){
        sz += a.sz;
        for(int i = 1;i <= k;i ++){
            mn[i] = min(mn[i],a.mn[i]);
            mx[i] = max(mx[i],a.mx[i]);
        }
    }
    bool operator<(const node&p)const{
        for(int i = 1;i <= k;i ++){
            if(mx[i] > p.mn[i]) return false;
        }
        return true;
    }
};
set<node> s;
vector<set<node>::iterator>del;
int main(){
    scanf("%d %d",&n,&k);
    node now;
    for(int i = 1;i <= n;i ++){
        for(int j = 1;j <= k;j ++)
        scanf("%d",&now.mn[j]),now.mx[j] = now.mn[j];
        now.sz = 1;
        set<node>::iterator l,r,iter;
        //l = lower_bound(s.begin(),s.end(),now);
        //r = upper_bound(s.begin(),s.end(),now);
        r = s.upper_bound(now);
        l = s.lower_bound(now);
        for(iter = l;iter != r;iter ++){
            now.unit(*iter);
            del.push_back(iter);
        }
        for(int j = 0;j< del.size();j ++){
            s.erase(del[j]);
        }
        del.clear();
        s.insert(now);
        iter = s.end();
        iter --;
        printf("%d\n",iter->sz);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值