Codeforces Round 922 (Div. 2)
基本情况
A、B秒了,C二进制拆位处理短板,卡了很久,D没想出来,甚至二分都没考虑。
C. XOR-distance
这题算是给我上了一课,
二进制拆位处理真该好好学学了。
思路
思路很好想,从高位往低位处理:
- 先找到最高的不同的位
- 如果是上 \(1\) 下 \(0\),说明结果最高位是正的。
- 如果是上 \(0\) 下 \(1\),说明结果最高位是正的。
- 之后找每一个不同的位
- 如果最高位是正的,就只对 上 \(1\) 下 \(0\) 的情况取反处理。
- 如果最高位是负的,就只对 上 \(0\) 下 \(1\) 的情况取反处理。
- 总结:同号取反处理,异号不作处理。
实现
由于第一次遇到这种题,所以啥都是从头开始。
- 判断 \(x\) 的二进制第 \(k\) 位是什么
我最开始是用了十进制类似处理方法,就每次把这个数左移一,然后按位与一,但是这样会改变数原来的数值。
后面想到了更简便的处理方法,但是用的是原数右移,也是很麻烦。
学习了最合适的方法 x & (1 << k)
。
原理很显然,算是一个 \(trick\) 。
其实破题关键点就是这个,我因为这个用的不是最方便的,导致了石山代码。
之后实现就按位处理即可。
void solve()
{
ll x, y, r;
cin >> x >> y >> r;
bool is_high = true;
ll now = 0;
for (ll i = 60; i >= 0; i--) {
bool px = (x & (1LL << i)), py = (y & (1LL << i));//判断第i位的数码
if (px == py) continue;
if (is_high) {
now = (1LL << i) * (px - py);//最高位直接加上,不操作
is_high = false;
}
else {
if (r >= (1LL << i) && (px - py) * now > 0) {//同号且r还够,进行操作
r -= (1LL << i);
now -= (px - py) * (1LL << i);
}
else {//异号不用操作
now += (px - py) * (1LL << i);
}
}
}
if (now > 0) cout << now << endl;
else cout << -now << endl;
}
D. Blocking Elements
这题真的是技不如人了。
甚至正解的边都没碰到,一直在想贪心错解。
正解是二分,check时候要用到单调队列优化DP。
目前仅限于理解大体思路,感觉距离这道题还有很大距离,先放着。