大佬,带带我
题目描述
Eric决定在队里实行老队员带新队员的训练制度。Eric给队里的每个人都评估了一个能力值,如果A的能力值高于B的,那么A就可以带B。 但是每个人的都有自己的个性,可能会不喜欢某人,这样必然会影响训练的效果。所以,Eric要大家发邮件给他,告知不喜欢带哪些人,或者不喜欢被哪些人带。
现在,Eric给你一个任务,请计算一下,每个人能带的人的数量。
输入
只有一组样例,第一行是两个整数n(1≤n≤10000),m(0≤m≤n),分别表示队员的数量和收到的邮件数量。 第二行是n个整数,a1,a2,…,an,1≤ai≤109) 依次表示队员的能力值。 以后的m行,每行表示一个队员的邮件,第一个是一个整数i(1≤i≤n),表示第i个队员,第二个是一个整数k(1≤k≤n−1),表示他不喜欢的人的数量,以后的k个整数b1,b2,…,bk,表示不喜欢人的编号。
输入数据保证所有的邮件的发件人都是唯一的,其不喜欢人列表中也没有重复元素,也不会包含自己。 ∑mi=1ki≤106 , ki表示第i份邮件中不喜欢人的数量。
输出
输出一行,n个整数,为每个人能带的人的数量,之间用一个空格隔开,行尾无空格。
样例输入
5 3 10 3 10 4 15 1 1 2 5 3 1 2 3 4 1 5样例输出
1 0 2 1 0样例解释
1号,按能力值可以带2和4号,但是他不喜欢2号,所以只能带4号1个人。 2号,能力值最低,不能带任何人,所以是0个。 3号,按能力值可以带2和4号,他没有不喜欢谁,2和4号也都没有不喜欢他,所以他可以带2个人。 4号,按能力值可以带2号,两者没有不喜欢关系,所以4号可以带1个。 5号,按能力可以带1,2,3,4号,但是他不喜欢1,2,3号,4号又不喜欢他,所以他不能带任何人。
提示
巨大的输入量,请使用快读技术
解题思路:对照代码理解更方便
AC代码:
#include <stdio.h>
#include <stdlib.h>
struct Point{
int x,y;
} P[1000010];
int n,m,k,player1,player2,x0,y0,i,j,cnt;
int a[10010], find[10010], ans[10010];
int read() // 快读
{
char ch=getchar();int x=0,f=1;
while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int cmp1(const void *p1, const void *p2){
return *(int *)p1 - *(int *)p2;
}
int cmp2(const void *p1, const void *p2){ // 结构体排序
if (((Point *)p1)->x != ((Point *)p2)->x)
return ((Point *)p1)->x - ((Point *)p2)->x;
return ((Point *)p1)->y - ((Point *)p2)->y;
}
int main()
{
n = read(); m = read();
for (i = 1; i <= n; i ++) {a[i] = read();find[i-1] = a[i];}
qsort(find,n,4,cmp1); // 对find升序排序,这样在find数组中,a[i]的值排第几位,就有几个人能力小于i
for (i = 1; i <= n; i ++)
{
for (j = 0; find[j] < a[i]; j ++); // 找到有 j 个人 能力比 i 小
ans[i] = j; // i 按理说可以带 j 个人
}
P[0].x = -1; P[0].y = -1; // 插入一个无效元素,方便50行 i=1时 情况处理。
for (i = 1; i <= m; i ++) // 记录 不喜欢的人
{
player1 = read(); k = read();
for (j = 1; j <= k; j ++)
{
player2 = read(); // 把不喜欢的两人, 序号较小的放 x, 较大的放在 y. 以实现(x,y)=> (1,2)、(2,1) 都表示为(1,2)
if (player1 < player2) {P[cnt].x = player1; P[cnt].y = player2; ++cnt;}
if (player2 < player1) {P[cnt].x = player2; P[cnt].y = player1; ++cnt;}
}
}
qsort(P,cnt+1,sizeof(Point),cmp2); // 结构体排序
for (i = 1; i <= cnt; i ++)
{
if (P[i-1].x == P[i].x && P[i-1].y == P[i].y) continue; // 如果两人是第二次一起出现,跳过处理
x0 = P[i].x; y0 = P[i].y;
if (a[x0] > a[y0] && ans[x0] > 0) {ans[x0] -= 1;}
if (a[y0] > a[x0] && ans[y0] > 0) {ans[y0] -= 1;}
}
for (i = 1; i < n; i ++) // 依次输出最后结果
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
return 0;
}