社区讨论
警示后人:编译器 Bug
P5854【模板】笛卡尔树参与者 100已保存回复 118
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 118 条
- 当前快照
- 1 份
- 快照标识符
- @mihfkhkh
- 此快照首次捕获于
- 2025/11/27 20:49 3 个月前
- 此快照最后确认于
- 2025/11/28 23:58 3 个月前
本题的部分写法将左右子树定义为一个二维数组,第二维下标是 0 表示左子树,第二维下标为 1 表示右子树。如果你不幸地这么写代码,你有可能会发现:
- 对于大部分的本地平台开不开 O2,运行都很正常(假定你的本地没有 gcc15.1);
- 洛谷上使用 C++14(GCC9),开不开 O2 运行都很正常;
- 洛谷上使用其他的 C++ 语言,运行很不正常,甚至样例就挂了。
你可能会以为自己的代码存在未定义行为,嘿嘿错了,这是一个编译器 bug。编译器在试图优化这一段的时候,产生了【我也不知道为什么】的问题,然后就寄了。如果在其中任意做一些其他的操作,让编译器不去自动优化,就能通过。
CPPans1 ^= (1ll * i * (d[i][0] + 1));
ans2 ^= (1ll * i * (d[i][1] + 1));
也就是说,不管把编译器版本留在上古的 GCC9.3,还是最新的 GCC15.1/15.2,都会有明显干扰做题的编译器 Bug。所以,NOIP 写完的代码还是尽可能都在 NOI Linux 下测一下吧!
参考的完整代码(抄的题解第二篇):
CPP#include <bits/stdc++.h>
using namespace std;
char buf[1 << 21], *p1 = buf, *p2 = buf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1 ++)
inline int read() {
int x = 0, flag = 1;
char ch = getchar();
for( ; ch > '9' || ch < '0' ; ch = getchar()) if(ch == '-') flag = -1;
for( ; ch >= '0' && ch <= '9' ; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
return x * flag;
}
typedef long long LL;
const int MAXN = 1e7 + 50;
int n, A[MAXN], tack[MAXN], top = 1, d[MAXN][2];
LL ans1, ans2;
int main() {
n = read(); tack[1] = 1;
for(int i = 1 ; i <= n ; i ++) A[i] = read();
for(int i = 2 ; i <= n ; i ++) {
while(A[tack[top]] > A[i] && top) top --; // 弹栈
if(!top) d[i][0] = tack[top + 1]; // 如果右链中没有一个比它大的元素,它就成了右链的链顶并且原来的链顶就是它的左儿子
else d[i][0] = d[tack[top]][1], d[tack[top]][1] = i; // 想象一下把点 i 插入到某个点的下方,也就是说原本那个点的右儿子要变成 i 的左儿子,然后 i 来充当这个右儿子
tack[++ top] = i;
}
for(int i = 1 ; i <= n ; i ++) {
ans1 ^= (1ll * i * (d[i][0] + 1));
ans2 ^= (1ll * i * (d[i][1] + 1));
} printf("%lld %lld", ans1, ans2);
return 0;
}
// Author : MuYC
回复
共 118 条回复,欢迎继续交流。
正在加载回复...