1. 程式人生 > 其它 >AtCoder Regular Contest 120 C - Swaps 2(樹狀陣列)

AtCoder Regular Contest 120 C - Swaps 2(樹狀陣列)

題目連結:點我點我

Score : 500 points

Problem Statement

Given are two sequences of length N each: A=(A1,A2,A3,,AN) and B=(B1,B2,B3,,BN).
Determine whether it is possible to make A equal B by repeatedly doing the operation below (possibly zero times). If it is possible, find the minimum number of operations required to do so.

  • Choose an integer i such that 1i<N, and do the following in order:
    • swap Ai and Ai+1;
    • add 1 to Ai;
    • subtract 1 from Ai+1.

Constraints

  • 2N2×105
  • 0Ai109
  • 0Bi109
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A1 A2 A3  AN
B1 B2 B3  BN

Output

If it is impossible to make A equal B, print -1.
Otherwise, print the minimum number of operations required to do so.


Sample Input 1

3
3 1 4
6 2 0

Sample Output 1

2

We can match A with B in two operations, as follows:

  • First, do the operation with
    i=2
    , making A=(3,5,0).
  • Next, do the operation with i=1, making A=(6,2,0).

We cannot meet our objective in one or fewer operations.


Sample Input 2

3
1 1 1
1 1 2

Sample Output 2

-1

In this case, it is impossible to match A with B.


Sample Input 3

5
5 4 1 3 2
5 4 1 3 2

Sample Output 3

0

A may equal B before doing any operation.


Sample Input 4

6
8 5 4 7 4 5
10 5 6 7 4 1

Sample Output 4

7



給出兩個陣列,每個陣列有 n 個數,可以進行如下操作 :
將 a 陣列中的 a[i]->a[i]+1 與 a[i+1]->a[i+1]-1 然後再交換位置,問最少需要多少次操作可以將 a 陣列變為 b 陣列




先看一下第 4 組樣例該怎麼做,

\[8,5,4,7,4,5 \]

想讓第一個數變為 10,我們可以讓 7 移動到第一個位置上來,也可以讓最後一個 5 移動到第一個位置上來,但是就這一步而言讓 7 過來是最優的,而 7 前面的 8 5 4,分別要減去 1;
所以現在的思路有了,對於 b 陣列中的每一個位置 j,我們只要找到 a 陣列中 \(a[i]+i-j=b[j]\) 的第一個 \(a[i]\) 即可,時間複雜度 \(O(n^2)\)

這樣是遠遠不夠的,我們需要更快速地方法,我們將上式做一個變化

\[a[i]+i=b[j]+j \]

這個式子就很漂亮,這樣將 a 和 b 陣列同時變為 \((a[i]+i)\)
\((b[i]+i)\) 的形式,這樣 a ,b 陣列就分別變為了

\[9 ,7 ,7 ,11 ,9 ,11 \]\[11,7,9,11,9,7 \]

這個問題,兩個陣列相同,求交換多少次可以變成另一個數組,這不就是求 ‘逆序對’ 嗎


const int N = 3e5 + 5;

    ll n, m, _;
    int i, j, k;
    int a[N];
    int b[N], c[N];
    map<int, vector<int>> mp;

void add(int x)
{
    for(; x <= n; x += lowbit(x)){
        c[x] ++;
    }
}

int ask(int x)
{
    int ans = 0;
    for(; x; x -= lowbit(x)){
        ans += c[x];
    }
    return ans;
}

signed main()
{
    //IOS;
    while(~ sd(n)){
        rep(i, 1, n) sd(a[i]);
        rep(i, 1, n) sd(b[i]);
        ll ok = 0;
        per(i, 1, n){
            a[i] += i;
            b[i] += i;
            mp[b[i]].pb(i);
            ok += a[i] - b[i];
        }
        rep(i, 1, n){
            int tmp = a[i];
            if(mp[a[i]].empty()){
                ok = 1;
                break;
            }
            a[i] = *mp[a[i]].rbegin();
            mp[tmp].pop_back();
        }
        if(ok){
            puts("-1");
            break;
        }
        ll ans = 0;
        per(i, 1, n){
            ans += ask(a[i]);
            add(a[i]);
        }
        pll(ans);
    }
    return 0;
}