题意:
有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;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!