[CF 415E]Mashmokh and Reverse Operation

题目:

 http://codeforces.com/contest/415/problem/E

思路:

 查询次数很多,所以考虑预处理出每段的逆序对的个数,这里使用归并排序计算出每次一层归并所得的逆序对和正序对。在之后的每次查询时,把受到影响的部分减去,加上原来的正序对即是答案。

代码:

#include <cstdio>

using namespace std;
const int maxn = (1 << 20) + 5;
typedef long long ll;
#define FOR(i, a, b) for(int i = a; i <= b; i++)

int K, N, Q;
ll A[maxn], B[maxn];
ll INV[21][2];
bool H[21];

void init(int l, int r, int d) {
    if(l == r) return;
    int m = (l + r) >> 1;
    init(l, m, d + 1);
    init(m + 1, r, d + 1);

    int rl = m + 1;
    FOR(i, l, m) {
        while(rl <= r && A[rl] < A[i]) rl++;
        INV[d][0] += rl - m - 1;
    }
    rl = l;
    FOR(i, m + 1, r) {
        while(rl <= m && A[rl] < A[i]) rl++;
        INV[d][1] += rl - l;
    }

    int ll = l,  cur = l;
    rl = m + 1;
    while(ll <= m && rl <= r) {
        if(A[ll] < A[rl]) B[cur++] = A[ll], ll++;
        else B[cur++] = A[rl], rl++;
    }
    while(ll <= m) B[cur++] = A[ll], ll++;
    while(rl <= r) B[cur++] = A[rl], rl++;
    FOR(i, l, r) A[i] = B[i];
}

int main() {
    ll sum = 0;
    scanf("%d", &N);
    K = 1 << N;
    FOR(i, 1, K)
        scanf("%lld", &A[i]);

    init(1, K, 0);

    FOR(i, 0, N) sum += INV[i][0];

    scanf("%d", &Q);
    while(Q--) {
        int tmp;
        scanf("%d", &tmp);
        FOR(i, N - tmp, N)
            sum = sum - INV[i][ H[i] ] + INV[i][ H[i] ^=1 ];
        printf("%lld\n", sum);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值