1. 程式人生 > >Tournament

Tournament

view tarjan nod fine != its main 技術 bits

題意:

有 $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

Tournament