信息学奥赛刷题日记:P1197 星球大战,直接爆了!

2024-05-11 16:39:29 浏览数 (1)

先说现象:

  • 首先:小码匠的代码在windows上是通过样例;
  • 其次:我拿到她的代码,在我的mac上也跑了下,也正常通过;

我当时就感觉很纳闷,这是怎么回事呢。

注意点1:有时候macOS上能正常跑的代码,到Windows上可能直接就挂了。

之前遇到过一次,例如bool型变量你不付出值,windows和macOS默认的初始值是不同的。

这个和操作系统用的编译器有关系。

既然windows和macOS都能正常运行,那到底是啥原因呢。

我们先看下小码匠写的代码,是不是很帅气啊。

这点还是很有自信的,小码匠的码风可以秒杀95%以上oier选手。

代码语言:javascript复制
#include <bits/stdc  .h>

using namespace std;

const int maxn = 2e5   5;
int fa[maxn], close[maxn];
bool open[maxn];
vector<int> g[maxn];

int Find(int a) {
    if (a != fa[a]) {
        fa[a] = Find(fa[a]);
    }
    return fa[a];
}

void Union(int x, int y) {
    int a = Find(x);
    int b = Find(y);
    if (a != b) {
        fa[max(a, b)] = min(a, b);
    }
}

bool same(int x, int y) {
    return Find(x) == Find(y);
}

void best_coder() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n;   i) {
        fa[i] = i;
        open[i] = true;
    }
    for (int i = 0; i < m;   i) {
        int a, b;
        cin >> a >> b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int k;
    cin >> k;
    for (int i = 0; i < k;   i) {
        cin >> close[i];
        open[close[i]] = false;
    }

    int cnt = n - k;
    for(int i = 0; i < n;   i){
        if (!open[i]) {
            continue;
        }
        for (auto j : g[i]) {
            if (open[j] && !same(i, j)) {
                Union(i, j);
                --cnt;
            }
        }
    }
    stack<int> ans;
    ans.push(cnt);
    for (int i = k - 1; i >= 0; --i) {
          cnt;
        open[close[i]] = true;
        for (auto j : g[close[i]]) {
            if (open[j] && !same(close[i], j)) {
                Union(close[i], j);
                --cnt;
            }
        }
        ans.push(cnt);
    }
    while (!ans.empty()) {
        cout << ans.top() << 'n';
        ans.pop();
    }
}

void happy_coder() {

}

int main() {
    // 提升cin、cout效率
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    // 小码匠
    best_coder();

    // 最优解
    // happy_coder();

    return 0;
}

我们截取错误日志的一部分内容

先抛出一个小问题:你能看出是什么问题吗?

代码语言:javascript复制
/tmp/compiler_hvhxk0fa/src:12:25: 错误:‘int close [200005]’ redeclared as different kind of entity
   12 | int fa[maxn], close[maxn];
      |                         ^
In file included from /nix/store/79624djlfdc0a6anji2rwqd9p9ycqi8h-glibc-2.34-210-dev/include/bits/sigstksz.h:24,
                 from /nix/store/79624djlfdc0a6anji2rwqd9p9ycqi8h-glibc-2.34-210-dev/include/signal.h:328,
                 from /nix/store/bbmwawbq7wjb54fa35wr72alcm083d1f-luogu-gcc-9.3.0/include/c  /9.3.0/csignal:42,
                 from /nix/store/bbmwawbq7wjb54fa35wr72alcm083d1f-luogu-gcc-9.3.0/include/c  /9.3.0/x86_64-unknown-linux-gnu/bits/stdc  .h:43,
                 from /tmp/compiler_hvhxk0fa/src:7:
/nix/store/79624djlfdc0a6anji2rwqd9p9ycqi8h-glibc-2.34-210-dev/include/unistd.h:358:12: 附注:previous declaration ‘int close(int)’
  358 | extern int close (int __fd);
      |            ^~~~~
/tmp/compiler_hvhxk0fa/src: 在函数‘void best_coder()’中:
/tmp/compiler_hvhxk0fa/src:51:23: 警告:在算术表达式中使用了函数指针 [-Wpointer-arith]
   51 |         cin >> close[i];

说来很惭愧,我当时没有仔细看日志,一通删减代码找原因,结果搞了半天也没能查出来。

后来有点晚了,就想睡觉,突然间灵光一闪,又想看看日志到底怎么回事。

定睛一看,错误指向的是

代码语言:javascript复制
close[maxn];

我当时就很纳闷,太搞了,开头定义了fa和close两个int数组,为啥close有问题呢?

代码语言:javascript复制
const int maxn = 2e5   5;
int fa[maxn], close[maxn];
bool open[maxn];
vector<int> g[maxn];

回过头来我在仔细看日志

代码语言:javascript复制
/tmp/compiler_hvhxk0fa/src:12:25: 错误:‘int close [200005]’ redeclared as different kind of entity
   12 | int fa[maxn], close[maxn];

日志中提到【redeclared】,莫非框架底层用到这个变量了,所以重定义了。

我迅速重构代码

代码语言:javascript复制
close[maxn];

改成

代码语言:javascript复制
close1[maxn];

扔到洛谷上,哇塞!直接90分。

这个让我回想起之前整理过的坑。

相关的坑后面我在整理,先下个结论。

孩子们在编写代码的时候,变量名不能随便起,可能会和底层的变量重名

例如:变量名不要起成:j0, j1,很可能你本地能跑,提交就挂,这个可是0分,直接爆零,是直接爆零啊。

好啦!今天就写到这里。

0 人点赞