【数据结构】CF1416C - XOR Inverse

链接:https://codeforces.com/contest/1416/problem/C

显然是要从最高位往下贪。有个暴力的做法是每一层套一个树状数组求逆序对,然后愉快的TLE了。

优化的办法是每一次要利用上一次的信息(反过来的基数排序),总的来说是这样:

第29位:全区间排序
第28位:分高位为 \(\{0,1\}\) 分别排序
第27位:分高位为 \(\{00,01,10,11\}\) 分别排序
第26位:分高位为 \(\{000,001,010,011,100,101,110,111\}\) 分别排序

做到“分别排序”这个功能,每次取出一段连续的高位相同的区间,即可。

int n;
int a[300005];
int b[300005];

void solve() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);

    ll ans = 0;
    int x = 0, highmask = (1 << 30);
    for(int bit = 29; bit >= 0; --bit) {
        ll sum0 = 0, sum1 = 0;
        int curmask = (1 << bit);
        for(int l = 1, r; l <= n; l = r + 1) {
            for(r = l; r + 1 <= n && (a[r]&highmask) == (a[r + 1]&highmask); ++r);
            int cnt0 = 0, cnt1 = 0;
            for(int i = l; i <= r; ++i) {
                if(a[i]&curmask) {
                    ++cnt1;
                    sum1 += cnt0;
                } else {
                    ++cnt0;
                    sum0 += cnt1;
                }
            }
        }
        if(sum0 <= sum1) {
            ans += sum0;
            int btop = 0;
            for(int l = 1, r; l <= n; l = r + 1) {
                for(r = l; r + 1 <= n && (a[r]&highmask) == (a[r + 1]&highmask); ++r);
                for(int i = l; i <= r; ++i) {
                    if(!(a[i]&curmask))
                        b[++btop] = a[i];
                }
                for(int i = l; i <= r; ++i) {
                    if((a[i]&curmask))
                        b[++btop] = a[i];
                }
            }
        } else {
            ans += sum1;
            x |= curmask;
            int btop = 0;
            for(int l = 1, r; l <= n; l = r + 1) {
                for(r = l; r + 1 <= n && (a[r]&highmask) == (a[r + 1]&highmask); ++r);
                for(int i = l; i <= r; ++i) {
                    if((a[i]&curmask))
                        b[++btop] = a[i] ^ curmask;
                }
                for(int i = l; i <= r; ++i) {
                    if(!(a[i]&curmask))
                        b[++btop] = a[i] ^ curmask;
                }
            }
        }
        highmask |= curmask;
        for(int i = 1; i <= n; ++i)
            a[i] = b[i];
    }

    printf("%lld %d\n", ans, x);
    return;
}
上一篇:5-1异或(XOR)运算进行加密解密


下一篇:与或非运算