[Mivik Round 2021] [题解] Mirror
欢迎到我的博客查看
Subtask 1
由于可以直走,两个点之间要走多少格就是它们的曼哈顿距离了,然后中间需要拆除的障碍物直接判一下就好了。
Subtask 2
如果你善于观察,那么你会发现当起点位于
我们注意到时刻都必须有
x: 100
y: 011
然后 lowbit 是
x: 100
y: 010
lowbit 是
x: 100
y: 000
然后直接走到
综上,我们模拟一下上面那个过程就好了。
mivik.h
// Mivik 2021.1.6
#include <mivik.h>
#include <algorithm>
#include <list>
using std::list;
MI cin;
typedef long long qe;
const int N = 200005;
struct point { qe x, y; };
template<> struct Q<point> { inline void operator()(MI &r, point &t) {
r > t.x > t.y;
} };
int N;
point st, en, bar[N];
bool vis[N];
list<int> rem; // 还没被处理的障碍物
int main() {
cin > n;
for (int i = 1; i <= n; ++i) {
cin > bar[i];
rem.push_back(i);
}
cin > st > en;
if (st.x || st.y) {
cout < "Orz\n";
return 0;
}
auto &[x, y] = en;
cout < (x + y) < endl;
for (int i = 0; i < 60; ++i) { // 扫描 lowbit
if ((x >> i) & 1) {
const qe to = x & (x - 1);
for (auto it = rem.begin(); it != rem.end(); ) {
auto &p = bar[*it];
if (p.y == y && to <= p.x && p.x <= x) {
vis[*it] = 1;
it = rem.erase(it);
} else ++it;
}
x = to;
} else if ((y >> i) & 1) {
const qe to = y & (y - 1);
for (auto it = rem.begin(); it != rem.end(); ) {
auto &p = bar[*it];
if (p.x == x && to <= p.y && p.y <= y) {
vis[*it] = 1;
it = rem.erase(it);
} else ++it;
}
y = to;
}
}
for (int i = 1; i <= n; ++i) cout < vis[i];
cout < endl;
}
满分做法
实际上我们可以递归。每次把一个宽和高都为
根据我们在 Subtask 2 中得到的结论,在一个块内的点是可以用
实际上我们只需要判断一下
时间复杂度
mivik.h
代码