P6687 逆序对

题意

传送门 P6687 论如何玩转 Excel 表格

题解

正方形区域旋转之后,原本位于同一列的元素仍位于同一列,上下位置交换且在行方向上平移一个单位。若两个状态 A , B A,B A,B 相互可达,则存在列 i ∈ A , j ∈ B i\in A,j\in B iA,jB 使两列元素集合相同,且其中某一列在行方向上平移 ∣ i − j ∣ \lvert i-j\rvert ij 个单位后,两列元素次序一致。

将每一列元素看作一个元素,目标状态为有序状态,则答案为逆序对的个数。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l, _ = r; i < _; ++i)
typedef long long ll;
const int maxn = 1000005;
int N, A[2][maxn], B[2][maxn], pos[maxn << 1][2];
int C[maxn], bit[maxn];

int sum(int i)
{
    
    
    int s = 0;
    while (i)
        s += bit[i], i -= i & -i;
    return s;
}

void add(int i)
{
    
    
    while (i <= N)
        ++bit[i], i += i & -i;
}

int main()
{
    
    
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> N;
    rep(i, 0, 2) rep(j, 0, N) cin >> A[i][j], pos[A[i][j]][0] = i, pos[A[i][j]][1] = j;
    rep(i, 0, 2) rep(j, 0, N) cin >> B[i][j];
    rep(j, 0, N)
    {
    
    
        int b = B[0][j], ai = pos[b][0], aj = pos[b][1];
        if (A[ai ^ 1][aj] != B[1][j])
        {
    
    
            cout << "dldsgay!!1" << '\n';
            return 0;
        }
        if ((abs(j - aj) & 1) != ai)
        {
    
    
            cout << "dldsgay!!1" << '\n';
            return 0;
        }
        C[aj] = j;
    }
    ll res = 0;
    rep(i, 0, N)
    {
    
    
        res += i - sum(C[i] + 1);
        add(C[i] + 1);
    }
    cout << res << '\n';
    return 0;
}

Guess you like

Origin blog.csdn.net/neweryyy/article/details/120003785