【数据结构】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;
}
标签:Inverse,XOR,高位,int,CF1416C,分别,300005,排序 来源: https://www.cnblogs.com/purinliang/p/13742779.html