AtCoder Regular Contest 120 C - Swaps 2(樹狀陣列)
題目連結:點我點我
Score : points
Problem Statement
Given are two sequences of length each: and .
Determine whether it is possible to make equal 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 such that , and do the following in order:
- swap and ;
- add to ;
- subtract from .
Constraints
- All values in input are integers.
Input
Input is given from Standard Input in the following format:
Output
If it is impossible to make equal , 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 with in two operations, as follows:
- First, do the operation with
- Next, do the operation with , making .
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 with .
Sample Input 3
5 5 4 1 3 2 5 4 1 3 2
Sample Output 3
0
may equal 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 陣列就分別變為了
這個問題,兩個陣列相同,求交換多少次可以變成另一個數組,這不就是求 ‘逆序對’ 嗎
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;
}