题目大意:
不说。
题解:
如果x能胜y,则x往y连一条边。
如果一个点能够遍历所有的点,显然它就是可以的。
用tarjan缩一下强联通分量,入度为0的那个分量就是答案。
这样就有60分。
用主席树优化一下连边。
大概是线段树区间会下放到log个完整区间,直接往那些区间连边。
那些区间往包含的点连边。
注意插入有时效性,所以要用主席树的那种思想,新开点。
#include<cstdio>
#include<algorithm>
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 1e5 + 5, M = 1e7 + 2e6, D = 6e6;
int n, td, c[N], d[M];
struct node {
int i, a, b, c;
} a[N];
int c1(node a, node b) {return a.a < b.a;}
int c2(node a, node b) {return a.b < b.b;}
int c3(node a, node b) {return a.c < b.c;}
int final[D], next[M], to[M], tot, rt;
void link(int x, int y) {next[++ tot] = final[x], to[tot] = y, final[x] = tot;}
int pl, pr, px;
struct tree {
int l, r;
} t[D];
void fi(int &i, int x, int y) {
if(y < pl || x > pr) return;
if(!i) return;
if(x >= pl && y <= pr) {link(px, i); return;}
int m = x + y >> 1;
fi(t[i].l, x, m); fi(t[i].r, m + 1, y);
}
void add(int &i, int x, int y) {
if(y < pl || x > pr) return;
t[++ td] = t[i];
link(td, px); if(i) link(td, i);
i = td;
if(x == y) return;
int m = x + y >> 1;
add(t[i].l, x, m); add(t[i].r, m + 1, y);
}
void GG() {
rt = 0;
fo(i, 1, n) {
pl = 1; pr = c[i] - 1; px = d[i];
fi(rt, 1, n);
pl = pr = c[i]; px = d[i];
add(rt, 1, n);
}
}
int win(int i, int j) {
return (a[i].a > a[j].a) + (a[i].b > a[j].b) + (a[i].c > a[j].c);
}
int dfn[D], low[D], tt, fa[D], tf, bd[D];
int zx[M], zi[M], z0;
bool bz[M];
void dg(int x) {
zx[z0 = 1] = x; bz[z0] = 0;
int ti;
while(z0) {
ti = 0; x = zx[z0];
if(bz[z0]) {
int i = zi[z0]; low[x] = min(low[x], low[to[i]]);
for(i = next[i]; i; i = next[i]) {
int y = to[i];
if(!dfn[y]) {
zi[z0] = i; bz[z0] = 1;
++ z0;
zx[z0] = y; bz[z0] = 0;
ti = 1; break;
} else {
if(bd[y]) low[x] = min(low[x], dfn[y]);
}
}
if(ti) continue;
if(dfn[x] == low[x]) {
tf ++;
do {
fa[d[d[0]]] = tf; bd[d[d[0]]] = 0;
} while(d[d[0] --] != x);
}
} else {
dfn[x] = low[x] = ++ tt;
bd[x] = 1; d[++ d[0]] = x;
for(int i = final[x]; i; i = next[i]) {
int y = to[i];
if(!dfn[y]) {
zi[z0] = i; bz[z0] = 1;
++ z0;
zx[z0] = y; bz[z0] = 0;
ti = 1; break;
} else {
if(bd[y]) low[x] = min(low[x], dfn[y]);
}
}
if(ti) continue;
if(dfn[x] == low[x]) {
tf ++;
do {
fa[d[d[0]]] = tf; bd[d[d[0]]] = 0;
} while(d[d[0] --] != x);
}
}
z0 --;
}
}
int main() {
freopen("champion.in", "r", stdin);
freopen("champion.out", "w", stdout);
scanf("%d", &n);
fo(i, 1, n) a[i].i = i, scanf("%d %d %d", &a[i].a, &a[i].b, &a[i].c);
sort(a + 1, a + n + 1, c1);
fo(i, 1, n) a[i].a = i;
sort(a + 1, a + n + 1, c2);
fo(i, 1, n) a[i].b = i;
sort(a + 1, a + n + 1, c3);
fo(i, 1, n) a[i].c = i;
td = n;
sort(a + 1, a + n + 1, c1);
fo(i, 1, n) c[i] = a[i].b, d[i] = a[i].i;
GG();
sort(a + 1, a + n + 1, c2);
fo(i, 1, n) c[i] = a[i].c, d[i] = a[i].i;
GG();
sort(a + 1, a + n + 1, c3);
fo(i, 1, n) c[i] = a[i].a, d[i] = a[i].i;
GG();
fo(i, 1, n) d[i] = i;
fo(i, 1, n - 1) if(win(d[i - 1], d[i])) swap(d[i - 1], d[i]);
int g = a[d[n]].i;
dg(g);
fo(i, 1, n) if(fa[i] == fa[g])
printf("%d\n", i);
}