BZOJ2141/BSOJ3904 排队

BZOJ2141/BSOJ3904 排队

题意:给定一个序列,求逆序对个数,每次可以交换两个数。(\(n\leq 2*10^4\) ,\(m\leq 2*10^3\)

直接先处理第一次的答案,然后再考虑交换对答案的贡献。

因为 \(n,m\)都很小,所以可以直接暴力查询每次改变的量即可。

时间复杂度 \(O(nlogn+nm)\)

yhx的做法:

然后就行了,因为我是口胡,所以再贴一下他的代码。

#include <bits/stdc++.h>
#define sgn(i, j) ((a[i] > a[j]) - (a[i] < a[j])) // sgn(c[i] - c[j])
#define N 20034
using namespace std;

int n, q, i;
int l, r, ans = 0;
int a[N], buf[N], tmp[N];

int MergeSort(int L, int R){ // mergesort[L, R)
    if(L + 1 == R) return L;
    int M = L + R >> 1;
    MergeSort(L, M);
    MergeSort(M, R);
    int i, j, k = L;
    memcpy(tmp + L, buf + L, M - L << 2);
    for(i = L, j = M; i < M || j < R; )
        if(j >= R || (i < M && tmp[i] <= buf[j]))
            buf[k++] = tmp[i++];
        else{
            buf[k++] = buf[j++];
            ans += M - i;
        }
    return L;
}

int main(){
    scanf("%d", &n);
    for(i = 1; i <= n; i++)
        scanf("%d", a + i);
    memcpy(buf + 1, a + 1, n << 2);
    MergeSort(1, n + 1);
    printf("%d\n", ans);
    for(scanf("%d", &q); q; q--){
        scanf("%d%d", &l, &r);
        if(l > r) swap(l, r);
        if(a[l] == a[r]){
            printf("%d\n", ans);
            continue;
        }
        for(i = l; i < r; i++)
            ans += sgn(i, l) + sgn(r, i);
        swap(a[l], a[r]);
        printf("%d\n", ans);
    }
    return 0;
}

yhx's solution

posted @ 2021-04-13 14:46  __Anchor  阅读(30)  评论(0编辑  收藏  举报