codeforces 730E (數學)

題目鏈接:點擊這裏

題意:給出一個封榜時的榜單,按照封榜時的分數排序,每個隊伍在封榜後分數會改變,名次也會對應的變化t名。現在要求一個揭曉的順序最大化t

對於兩個隊伍i,j,考慮揭曉他們的相對順序。如果這兩個隊在揭曉前和揭曉後相對排名不同,那麼說明無論先揭曉哪個隊伍,最後對答案的貢獻總是1(畫個圖很容易看出來)。如果兩個隊揭曉前後相對排名不變,就分兩種情況考慮:
1. 無論先後揭曉順序如何,都不會使得一個隊伍越過另一個隊伍,這樣的情況下顯然先後順序無所謂,對答案的貢獻都是0;
2. 假設先揭曉i以後i的排名變化能夠越過j,然後再揭曉j以後j的排名又會重新越過i,那麼揭曉的順序就先i後j,對答案的貢獻是2,同理的情況亦然。
按照上述的方法,必然能夠得到一個拓撲網絡,然後按照拓撲關係即可得到一個揭曉的先後序列(當然題目沒有要求,只要確定最大值即可)。
現在來證明這樣的做法得到的關係圖沒有環
因爲只有第二種情況的第二點纔會給關係圖增加一條邊,所以環只會在這裏產生。假設有三個隊伍i,j,k構成一個環,那麼i揭曉後越過j,j揭曉後又重新越過i,jk和ki同理。顯然這種情況不存在,因爲ijk的相對次序必然是確定的,揭曉後的名次改變方向也必須一致,那麼(i改變後越過j),(j改變後越過k)與(k改變後越過i相矛盾),如圖:
這裏寫圖片描述
於是不存在環關係,證畢。

#include <bits/stdc++.h>
using namespace std;
#define maxn 105

struct node {
    int num, id, add;
    bool operator < (const node &a) const {
        return num > a.num || (num == a.num && id < a.id);
    }
}a[maxn];
int pre[maxn];
int n;

int ok (int i, int j) {
    node x = a[i], y = a[j], xx = x, yy = y;
    xx.num = x.num+x.add, yy.num = y.num+y.add;
    if (x < y && yy < xx) return 1;
    if (y < x && xx < yy) return 1;
    if (x < y && y < xx && xx < yy) return 2;
    if (y < x && x < yy && yy < xx) return 2;
    if (x < y && yy < x && xx < yy) return 2;
    if (y < x && xx < y && yy < xx) return 2;
    return 0;
}

int main () {
    //freopen ("more.in", "r", stdin);
    int ans = 0;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].num >> a[i].add;
        a[i].id = i;
    }
    sort (a+1, a+1+n);
    for (int i = 1; i <= n; i++) {
        for (int j = i+1; j <= n; j++) {
            ans += ok (i, j);
        }
    }
    cout << ans << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章