题目描述
You are working for an agency that selects the best software engineers from Belgium, the Netherlands and Luxembourg for employment at various international companies. Given the very large number of excellent software engineers these countries have to offer, the agency has charged you to develop a tool that quickly selects the best candidates available from the agency’s files.
Before a software engineer is included in the agency’s files, he has to undergo extensive testing. Based on these tests, all software engineers are ranked on three essential skills: communication skills, programming skills, and algorithmic knowledge. The software engineer with rank one in the category algorithmic knowledge is the best algorithmic expert in the files, with rank two the second best, etcetera.
For potential customers, your tool needs to process the agency’s files and produce a shortlist of the potentially most interesting candidates. A software engineer is a potential candidate that is to be put on this shortlist if there is no other software engineer in the files that scores better on all three skills. That is, an engineer is to be put on the shortlist if there is no other software engineer that has better communication skills, better programming skills, and more algorithmic knowledge.
简单化成中文来讲,就是每个人有三个排名x,y,z,如果一个人三个排名都小于某个人,那么他就没有被选中的必要,求有多少个人落选。
数据范围
T<=100N<=100000 T <= 100 N <= 100000
分析
第一眼看到这道题,就感觉是数据结构题,但开始做时发现有三维,首先根据 x x 排序可以少掉一维,然后以作为线段树下标, z z <script type="math/tex" id="MathJax-Element-70">z</script>作为维护的值,那么问题就解决了。
#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
int _read(){
char ch = getchar();
int x = 0 , f = 1 ;
while( !isdigit( ch ) )
if( ch == '-' ) f = -1 , ch = getchar();
else ch = getchar();
while( isdigit( ch ) )
x = (ch - '0') + x * 10 , ch = getchar();
return x * f;
}
const int INF = 0x7f7f7f7f;
const int maxn = 1e5 + 10;
struct segnode{
int l , r;
int v;
segnode *lc, *rc;
} pool[maxn * 4] , *tail = pool;
inline segnode* newnode(){ return tail++; }
inline int _min( int a , int b ){ return a > b ? b : a; }
void build( int l , int r , segnode *rt ){
rt->l = l , rt->r = r;
if( l == r ){
rt->v = INF;
rt->lc = rt->rc = NULL;
return;
}
int mid = (l + r) >> 1;
build( l , mid , rt->lc = newnode() );
build( mid + 1 , r , rt->rc = newnode() );
rt->v = _min( rt->lc->v , rt->rc->v );
}
void modify( int pos , int v , segnode *rt ){
if( rt->l == rt->r ){
rt->v = v;
return;
}
int mid = (rt->l + rt->r) >> 1;
if( pos <= mid ) modify( pos , v , rt->lc );
else modify( pos , v , rt->rc );
rt->v = _min( rt->lc->v , rt->rc->v );
}
int query( int ql , int qr , segnode *rt ){
if( ql <= rt->l && rt->r <= qr ){
return rt->v;
}
int mid = (rt->l + rt->r) >> 1 , ret = INF;
if( qr > mid ) ret = _min( ret , query( ql , qr , rt->rc ) );
if( ql <= mid ) ret = _min( ret , query( ql , qr , rt->lc ) );
return ret;
}
struct node{
int x , y , z;
}A[maxn];
inline bool cmp( node a , node b ){
return a.x < b.x;
}
int main(){
int T = _read() , N;
while( T-- ){
tail = pool;
N = _read();
rep( i , 1 , N )
A[i].x = _read() , A[i].y = _read() , A[i].z = _read();
sort( A + 1 , A + N + 1 , cmp );
segnode *root = newnode();
build( 1 , N , root );
int ans = 0;
rep( i , 1 , N ){
if( A[i].y != 1 ){
int t = query( 1 , A[i].y - 1 , root );
if( A[i].z > t ) continue;
}
ans++;
modify( A[i].y , A[i].z , root );
}
cout << ans << endl;
}
return 0;
}