标签:Inverse XOR 高位 int CF1416C 分别 300005 排序
链接: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
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。