Tournament

题意:

有 $n$ 个 $K$ 维向量,若向量A只要有任意一维大于向量B,则认为A可能打败B,将n个向量一个一个加入,求问对于每次加完后的向量集合:有几个向量可能活到最后。

 

解法:

考虑如果A可以打败B,则A到B连边,对得到的图tarjan,可以发现可能活到最后的向量在同一强联通分量。

考虑加入一个向量x,当x的每一维都大于给定强连通分量的Max,或都小于Min时,x才不能加入当前强连通分量。

这样可以发现,最终强连通分量构成一条链,用set维护这条链,每次lower_bound合并即可。

 

#include <bits/stdc++.h>

#define LL long long
#define LD double
#define FOR(i,a,b) for (int i = (a);i <= (b); i++)
#define DFOR(i,a,b) for (int i = (a);i >= (b); i--)
#define debug(x) cerr << "debug: " << (#x) << " = " << (x) <<endl;
#define PI acos(-1)
#define mp make_pair
#define pb push_back
#define itr iterator
#define bit(x) (1LL<<(x))
#define lb(x) ((x)&(-x))
#define sqr(x) ((x)*(x))
#define gn 3
#define l(x) ch[x][0]
#define r(x) ch[x][1]
#define y0 Y0
#define y1 Y1
#define y2 Y2
#define fir first
#define sec second

using namespace std;

const int N = 50010;

int n,K;

struct node {
    int M[10], m[10], sum;
    bool operator < (const node &tmp)const {
        FOR(i, 0, K-1) if(M[i] > tmp.m[i]) return false;
        return 1 ;
    }
};

multiset<node> tp;

int main() {
    scanf("%d %d", &n, &K);
    node tmp;
    FOR(i, 1, n) {
        FOR(i, 0, K-1) {
            scanf("%d", &tmp.m[i]);
            tmp.M[i] = tmp.m[i];
        }
        tmp.sum = 1;
        auto xx = tp.lower_bound(tmp);
        while(xx != tp.end() && !(tmp < *xx)) {
            FOR(i, 0, K-1) {
                tmp.m[i] = min(tmp.m[i], xx->m[i]);
                tmp.M[i] = max(tmp.M[i], xx->M[i]);
            }
            tmp.sum += xx->sum;
            tp.erase(xx++);
        }
        tp.insert(tmp);
        printf("%d\n", tp.rbegin()->sum);
    }
    return 0;
}
View Code

 

posted @ 2017-11-02 19:55  lawyer'  阅读(311)  评论(0编辑  收藏  举报