• 题解 P4812 【[COCI 2014/2015 #3]COCI】


    题目链接

    Soltuion [COCI 2014/2015 #3]COCI

    题目大意:有(n)个人,给定他们的第一轮成绩和第二轮成绩,如果(A)第一轮成绩和第二轮成绩均大于(B)的,那么(A)的第三轮成绩大于等于(B)的第三轮成绩。求每个人可能的最小、最大排名

    思维


    分析:

    首先最小排名等于成绩一定比他的人数(+1),这个比较显然。最大排名等于(n)减去成绩一定不高于他的人数

    先看最小排名,成绩一定比他高,满足以下两个条件之一(设当前这个人为(now),另一个人为(A),两次成绩为(X,Y)

    (1.egin{cases}X_{now}<X_A \ Y_{now}<Y_Aend{cases})

    (2.X_{now}+Y_{now}+650<X_A+Y_A)(哪怕你第三次阿克总分都没有另一个人第三次抱零高)被巨佬碾压

    满足第二个的条件的一定包含在第一个条件里面了,当第二个条件成立时,不妨假设(X_{now} geq X_{A})

    那么有(X_A-X_{now} leq0)

    由第二个条件推出(Y_{now}+650-Y_{A}<X_A-X_{now})

    由于(X,Yin[0,650]),不等号左边是个非负数,右边是个非正数,显然不成立。得证。

    所以求最小排名只需要一个前缀和。

    最大排名,成绩一定不高于他,满足以下两个条件之一

    (1.egin{cases}X_{now}>X_A \ Y_{now}>Y_Aend{cases})

    (2.X_{now}+Y_{now}geq X_A+Y_A+650)(哪怕你第三次抱零总分都不低于另一个人第三次阿克)巨佬碾压别人

    容斥原理可以算,我们证明满足第二个条件,但是不在第一个条件里面的最多只有两个点。

    仍假设第二个条件成立,假设(X_{now}leq X_A),那么有

    (X_{now}-X_{A}geq Y_A+650-Y_{now})

    (X_{now}-X_Aleq0)

    左边是个非正数,右边是个非负数,成立时两侧都为(0)

    (egin{cases}Y_{now}=650\X_A=X_{now}\Y_A=0end{cases})

    另一种情况同理,仍然前缀和来做

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    const int maxn = 5e5 + 100,maxk = 650;
    inline int read(){
    	int x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x;
    }
    struct node{int x,y;}val[maxn];
    int n,tmp[maxk + 10][maxk + 10],pre[maxk + 10][maxk + 10],suf[maxk + 10][maxk + 10];
    inline int query_pre(int x,int y){
    	if(x < 0 || y < 0)return 0;
    	return pre[x][y];
    }
    int main(){
    	n = read();
    	for(int i = 1;i <= n;i++)
    		val[i].x = read(),val[i].y = read();
    	for(int i = 1;i <= n;i++)
    		tmp[val[i].x][val[i].y]++;
    	pre[0][0] = tmp[0][0];
    	for(int i = 1;i <= 650;i++)
    		pre[0][i] = pre[0][i - 1] + tmp[0][i];
    	for(int i = 1;i <= 650;i++)
    		pre[i][0] = pre[i - 1][0] + tmp[i][0];
    	for(int i = 1;i <= 650;i++)
    		for(int j = 1;j <= 650;j++)
    			pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + tmp[i][j];
    	suf[650][650] = tmp[650][650];
    	for(int i = 649;i >= 0;i--)
    		suf[650][i] = suf[650][i + 1] + tmp[650][i];
    	for(int i = 649;i >= 0;i--)
    		suf[i][650] = suf[i + 1][650] + tmp[i][650];
    	for(int i = 649;i >= 0;i--)
    		for(int j = 649;j >= 0;j--)
    			suf[i][j] = suf[i + 1][j] + suf[i][j + 1] - suf[i + 1][j + 1] + tmp[i][j];
    	for(int i = 1;i <= n;i++){
    		int x = val[i].x,y = val[i].y;
    		int ans2 = query_pre(x - 1,y - 1) + (x == 650) * tmp[0][y] + (y == 650) * tmp[x][0];
    		printf("%d %d
    ",1 + suf[x + 1][y + 1],n - ans2);
    	}
    	return 0;
    }
    
  • 相关阅读:
    POJ3421(质因数分解)
    POJ2236(并查集入门)
    POJ3111(最大化平均值)
    POJ2976(最大化平均值)
    POJ3104(二分搜索)
    POJ3258(最大化最小值)
    POJ2456(最大化最小值)
    POJ1063Cable master(二分搜索)
    Numpy模块(一)
    Django简介
  • 原文地址:https://www.cnblogs.com/colazcy/p/13641498.html
Copyright © 2020-2023  润新知