题意:

有n个人,给出n个人在三个项目中的排名,要选出一些候选人,要求不是候选人里面没有比候选人三项都好的人。

思路:

理解能力是硬伤啊QAQ

这题目的意思是比如3 9 7和5 10 8,其中3 9 7每一项都比5 10 8好,所以5 10 8肯定不是候选人。

就是如果存在三项都比它好的人,那么这个人就肯定不是候选人。

假设三个项目排名分别是x,y,z。

所以可以先把所有人根据x排序,那么就满足了对于当前人,前面所有人的第一项排名都比他高。

那后面两项呢?可以用RMQ来做,对于当前这个人查询1~y-1看其中的最小值是不是比他小,这既满足了y比他小,而且z也比他小。然后把这个人插入到序列里,即a[y]=z。

这里这个RMQ我是用线段树实现的。

代码:

int n;
int ans;
struct node
{
    int x,y,z;
}a[100010];
bool cmp(node x,node y)
{
    return x.x<y.x;
}
struct Node
{
    int left,right,val;
}node[100010<<2];
void build(int l,int r,int id)   //建树
{
    node[id].left=l;
    node[id].right=r;
    if(l==r)
    {
        node[id].val=n+1;
        return;
    }
    int m=(l+r)>>1;
    build(l,m,id<<1);
    build(m+1,r,id<<1|1);
    node[id].val=min(node[id<<1].val,node[id<<1|1].val);
}
void update(int loc,int c,int id)   //单点修改
{
    int l=node[id].left;
    int r=node[id].right;
    if(l==r)
    {
        node[id].val=c;
        return;
    }
    int m=(l+r)>>1;
    if(loc<=m)update(loc,c,id<<1);
    else update(loc,c,id<<1|1);
    node[id].val=min(node[id<<1].val,node[id<<1|1].val);
}
void query(int L,int R,int id)   //区间查询
{
    int l=node[id].left;
    int r=node[id].right;
    if(l>=L&&r<=R)
    {
        //printf("val=%d\n",node[id].val);
        ans=min(ans,node[id].val);
        return;
    }
    int m=(l+r)>>1;
    if(L<=m)query(L,R,id<<1);
    if(R>m)query(L,R,(id<<1|1));
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
        sort(a+1,a+n+1,cmp);
        build(1,n,1);
        int tot=0;
        for(int i=1;i<=n;i++)
        {
            ans=INF;
            query(1,a[i].y-1,1);
            //printf("i=%d ans=%d\n",i,ans);
            if(ans<a[i].z)tot++;
            update(a[i].y,a[i].z,1);
            //printf("pos[%d]=%d\n",a[i].y,a[i].z);
        }
        printf("%d\n",n-tot);
    }
    return 0;
}