2012-09-26 21:01:05Morris

[ZJ][heap+計算] a373. 賽車

內容 :

有n輛賽車,從各不相同的位置出發,以各種速度開始往右行駛,不斷有超車現象發生


給定n輛賽車的出發位置Xi與速度Vi,請輸出超車事件的總數,以及依序列出最早發生的超車事件。
若有兩個超車事件同時發生,請先輸出超車位置數值較小的。 

輸入說明 :

第一列有一個正整數N (0< N <=250,000)
第二列開始有N列,每列包含兩個整數Xi和Vi代表第i輛車的初始位置與速度。
(0<=Xi<=1,000,000,0<Vi<=100,並且Xi依照嚴格遞增順序排列)

輸出說明 :

第一列請輸出超車事件總數除以1,000,000的餘數。

第二列開始請依序輸出超車事件。若全體的超車事件超過10,000個,那麼只要輸出前10,000個超車事件即可。
每一個超車事件可以用兩個數字表示i, j,代表i超越j。

範例輸入 :

4
0 2
2 1
3 8
6 3

範例輸出 :

2
3 4
1 2

提示 :

※測資保證不會有超車事件同時同地發生

出處 :

CEOI2003 The Race (管理:david942j)

首先先不對序列做任何排序, 總之最後會依照速度由小排到大,
我們先將"鄰近對"的放入超車可能, 將這些對放入 heap 中,
不過要注意有可能從 heap 丟出的最小已經不存在了, 那麼要檢查是否是相鄰的,

最後在限定的 10000 次之後, 採用 Merge Sort 去計算剩餘的交換次數,
紀錄這個排序是要 Stable Sort, 因此判斷時要注意一下

#include <cstdio>

#include <algorithm>
#include <queue>
using namespace std;
typedef struct {
    int x, v, i;
} Car;
typedef struct {
    double t, s;
    int a, b;
} ele;
struct cmp {
    bool operator() (ele a, ele b) {
        if(a.t != b.t)
            return a.t > b.t;
        return a.s > b.s;
    }
};
Car A[250000], X[250000];
int ans;
void Merge(int l, int m, int r) {
    int idx1 = l, idx2 = m+1, top = 0, i, j;
    int D = 0;
    while(idx1 <= m && idx2 <= r) {
        if(A[idx1].v <= A[idx2].v)
            X[top++] = A[idx1++], ans += D;
        else
            X[top++] = A[idx2++], D++;
        if(ans >= 1000000)  ans -= 1000000;
        if(D >= 1000000)    D -= 1000000;
    }
    while(idx1 <= m) {
        X[top++] = A[idx1++], ans += D;
        if(ans >= 1000000)
            ans -= 1000000;
    }
    while(idx2 <= r)    X[top++] = A[idx2++], D++;
    for(i = 0, j = l; i < top; i++, j++)
        A[j] = X[i];
}
void Msort(int l, int r) {
    if(l < r) {
        int m = (l+r)>>1;
        Msort(l, m);
        Msort(m+1, r);
        Merge(l, m, r);
    }
}
int main() {
    int n, i;
    int wh[250000];
    while(scanf("%d", &n) == 1) {
        for(i = 0; i < n; i++) {
            scanf("%d %d", &A[i].x, &A[i].v);
            A[i].i = i;
            wh[i] = i;
        }
        ele E, T;
        priority_queue<ele, vector<ele>, cmp> Q;
        for(i = 1; i < n; i++) {
            if(A[i-1].v > A[i].v) {
                E.a = A[i-1].i, E.b = A[i].i;
                E.t = (double)(A[i].x - A[i-1].x)/(A[i-1].v - A[i].v);
                E.s = A[i].x + E.t*A[i].v;
                Q.push(E);
            }
        }
        int cnt = 0, Ea[10000], Eb[10000];
        while(cnt < 10000 && !Q.empty()) {
            E = Q.top();
            Q.pop();
            if(wh[E.a]+1 == wh[E.b]) {
                Ea[cnt] = E.a+1, Eb[cnt] = E.b+1;
                cnt++;
                i = wh[E.a];
                swap(A[wh[E.a]], A[wh[E.b]]);
                wh[A[i].i] = i, wh[A[i+1].i] = i+1;
                i = wh[E.b];
                if(i-1 >= 0 && A[i-1].v > A[i].v) {
                    T.a = A[i-1].i, T.b = A[i].i;
                    T.t = (double)(A[i].x - A[i-1].x)/(A[i-1].v - A[i].v);
                    T.s = A[i].x + T.t*A[i].v;
                    Q.push(T);
                }
                i = wh[E.a];
                if(i+1 < n && A[i].v > A[i+1].v) {
                    T.a = A[i].i, T.b = A[i+1].i;
                    T.t = (double)(A[i+1].x - A[i].x)/(A[i].v - A[i+1].v);
                    T.s = A[i].x + T.t*A[i].v;
                    Q.push(T);
                }
            }
        }
        ans = 0;
        Msort(0, n-1);
        ans += cnt;
        printf("%d\n", ans);
        for(i = 0; i < cnt; i++)
            printf("%d %d\n", Ea[i], Eb[i]);
    }
    return 0;
}