【CROATIAN OPEN COMPETITION IN INFORMATICS 3rd round, November 29th, 2014】HONI

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

分析:计算i不可能超过的人,对于选手i,如果存在选手j满足S1i

#include<cstdio>
#define MAXN 500000
#define MAXS 650
int n,s1[MAXN+10],s2[MAXN+10];
int a[MAXS+5][MAXS+5],f1[MAXS+5][MAXS+5],f2[MAXS+5][MAXS+5];
void Read(int &x){
    char c;
    while(c=getchar(),c!=EOF){
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            return;
        }
    }
}
void read(){
    int i;
    Read(n);
    for(i=1;i<=n;i++){
        scanf("%d%d",&s1[i],&s2[i]);
        a[s1[i]][s2[i]]++;
    }
}
void solve(){
    int i,j;
    for(i=0;i<=MAXS;i++){
        for(j=0;j<=MAXS;j++){
            if(i>0&&j>0)
                f1[i][j]+=a[i-1][j-1]-f1[i-1][j-1];
            if(i>0)
                f1[i][j]+=f1[i-1][j];
            if(j>0)
                f1[i][j]+=f1[i][j-1];
        }
    }
    for(i=MAXS;i>=0;i--){
        for(j=MAXS;j>=0;j--){
            f2[i][j]+=a[i+1][j+1]-f2[i+1][j+1];
            f2[i][j]+=f2[i][j+1];
            f2[i][j]+=f2[i+1][j];
        }
    }
}
void print(){
    for(int i=1;i<=n;i++)
        printf("%d %d\n",1+f2[s1[i]][s2[i]],n-f1[s1[i]][s2[i]]-a[0][s2[i]]*(s1[i]==650)-a[s1[i]][0]*(s2[i]==650));
}
int main()
{
    read();
    solve();
    print();
}

你可能感兴趣的:(C++,dp,coci)