[羅区P1966]はキューに一致します

トピックリンク:

マッチキュー

トピック分析:

私はそれを起動することができることが、より論理的な感じ?問題のようです
あなたはおそらく上記とは逆になるでしょう言葉を交換し、その式の対象は怖いに使用されていますノー卵
あなただけが欲の波考慮伝えるおそらく使用し、あることは明らかである最適な戦略上のランクの番号を対応する各ペアの2つの配列が上の同じ位置され、この結論を
前提とし、詳細(A_0 \)\です\(A \)のシーケンス\(k個\)大、\は(B_0 \)\の(b \)の順に\(k個\)大きい、\(A_0 \)(B_0 \)\確かに交換する必要があります同じ位置に、そして次に減算されます。
その後、我々は、最小数のやり取りする方法を検討し
、最もシンプルで、粗交換方法を検討最初に:2つの配列が列をランク付けしたので、順位は確かに一から一です
ので、交換の回数が合計の逆の順序で順番に番号2がある
が、これは最善ではありません、と言う2つの配列はランキングは1423あります。我々はシーケンシングを指示した場合、我々はラインランキングで場所に彼を転送するために、数字のペアを取得することができるだろう為替が存在します(たとえば、一緒に前進し、変化し、2つの配列は1423年でしたが、直接の場合ソートが)このケースを交換することが不要、その後4と2を持っていますが、これは実際には答えに貢献されていません
し、我々はどのように最適化する検討し
、問題を発見し、実際にはこの数自体は問題ではありませんまず、主にいくつかの順位の関係、あなたが離散の配列を置くことができますので
、私は......最初のそれぞれ最初のシーケンスは何を再定義し、優先度の数を考える方法を知らないことを
例えば
1342
我々は、各要素は、優先度として定義され、それを取る
。1 2 4 3
3 4 2 1
(垂直に相当)
と、我々は我々自身の優先順位が2番目のシーケンスを再定義定義使用、第2の仮定は、
1423年
次いで我々は、に置き換え
1342年
、我々は、2つの新しい配列が得られた
。3 4 2 1
1 2 3 4は、
第一の配列が第二のスイッチング素子上の配列に、この時間は移動しないことを確認しますその上一致をランク付けする(なぜなら、実際には第一及び第二変化の変化の本質的に差がない)
のスイッチング周波数は数の逆の順序で第二の配列であるか、またはフェンウィックツリーソートマージ

コード:

私は上記の分析に焦点を当て、それは醜いですので、コードを急いで書かれている、マージを書いて、達成することは困難ではありません

#include <bits/stdc++.h>
#define int long long
#define N (100000 + 20)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
    return cnt * f;
}
int n, a[N], b[N << 1], a_[N], res, cnt, ans;
int New[N];
void Discretization(int a[]) {
    sort(b + 1, b + n + 1);
    int q = unique(b + 1, b + n + 1) - b;
    for (register int i = 1; i <= n; i++) 
        a[i] = lower_bound(b + 1, b + q + 1, a[i]) - b - 1;
}
int merge(int l, int r) {
    int mid = (l + r) >> 1;
    int i = l, j = mid + 1; cnt = 0;
    for (register int k = l; k <= r; k++) 
        if (j > r || (i <= mid && a_[i] < a_[j])) b[k] = a_[i++];
        else b[k] = a_[j++], cnt += (mid - i + 1) % 99999997;
    for (register int k = l; k <= r; k++) a_[k] = b[k];
    return cnt;
}
int solve(int l, int r) {
    if (l < r) {
        int mid = (l + r) >> 1;
        solve(l, mid), solve(mid + 1, r);
        ans += merge(l, r); 
    }
    return ans;
}
signed main() {
    n = read();
    for (register int i = 1; i <= n; i++) a[i] = b[i] = read();
    Discretization(a);
    for (register int i = 1; i <= n; i++) a_[i] = b[i] = read();
    Discretization(a_);
    for (register int i = 1; i <= n; i++) New[a[i]] = i;
    for (register int i = 1; i <= n; i++) a_[i] = New[a_[i]];
//  for (register int i = 1; i <= n; i++) cout<<a_[i]<<" ";
//  cout<<endl; 
    memset(b, 0, sizeof(b)); 
    res = solve(1, n) % 99999997;
    printf("%d", res % 99999997);
    return 0;
}

おすすめ

転載: www.cnblogs.com/kma093/p/11294334.html