COCI CONTEST #3 29.11.2014 HONI

题目大意:比赛已经进行到了第三场,开始有人预测第三场比赛选手们的排名了。怎么预测呢,我们假设存在以下的规律:
如果选手A在前两场比赛的分数都高于B,则第三场比赛选手A的分数不可能低于B。
排名的规则是这样的,总分相同则名次并列。比如说,如果有5个选手的分数为1000,1000,900,900,800,则他们的名次为1,1,3,3,5.
现在我们知道N个选手在前两场比赛的成绩,如果上述规律始终成立,预测每个选手的最高排名和最低排名。
比赛选手的分数在0~650之间。

思路:这道题非常好想到求一个二维的前缀和。假设选手A的成绩为a1, a2,那么我们将一个统计的数组M[a1][a2]增加1。然后统计M的前缀和为P,后缀和为S。A选手的最好排名就是S[a1+1][a2+1] + 1。那么是不是A选手的最坏成绩就是N-S[a1-1][a2-1]呢?其实不是,若存在两人 X、Y,X的成绩是(q, 0), Y的成绩是(q, 650)。那么Y的最坏成绩也是X的最好成绩,因为X第三次比赛如果取得了650分,他最多就是和Y持平。

代码:

#include<cstdio>
#define MAXP 666
#define MAXN 500006
int mt[MAXP][MAXP], n, q[MAXP][MAXP], h[MAXP][MAXP];
int f[MAXN], s[MAXN];
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d%d", &f[i], &s[i]);
        ++f[i]; ++s[i];
        mt[f[i]][s[i]] ++;
    }
    for(int i = 1; i <= 651; i ++)
    {
        int tmp = 0;
        for(int j = 1; j <= 651; j ++)
        {
            tmp += mt[i][j];
            if(i > 0) q[i][j] = tmp + q[i-1][j];
        }
    }
    for(int i = 651; i >= 1; i --)
    {
        int tmp = 0;
        for(int j = 651; j >= 1; j --)
        {
            tmp += mt[i][j];
            h[i][j] = tmp + h[i+1][j];
        }
    }
    for(int i = 1; i <= n; i ++)
        printf("%d %d\n", h[f[i]+1][s[i]+1] + 1, n - q[f[i]-1][s[i]-1] - (f[i] == 651) * mt[1][s[i]] - (s[i] == 651) * mt[f[i]][1]);
    return 0;
}

你可能感兴趣的:(coci)