DengStar @ 2024-08-30 18:03:26
RT,我尝试实现了一个封装版本的写法,在本地正常编译并且通过了样例,但在洛谷上 CE。编译信息如下:
No valid executable file was produced by the compiler
/nix/store/p58l5qmzifl20qmjs3xfpl01f0mqlza2-binutils-2.40/bin/ld: ./ccetxk7b.o:(.bss+0x0): multiple definition of `_init'; /nix/store/gqghjch4p1s69sv4mcjksb2kb65rwqjy-glibc-2.38-23/lib/crti.o:(.init+0x0): first defined here
collect2: 错误:ld 返回 1
网上有人说这可能是因为使用了万能头文件并且 using namespace std;
,但我删去了这一行之后仍然 CE,自己找不出原因,望大佬解答。
提交记录
代码:
// P3372 【模板】线段树 1
#include<bits/stdc++.h>
typedef long long i64;
constexpr int MAXN = 1e5 + 10;
int n, m, a[MAXN];
template<class Info, class Tag>
struct SegTree
{
#define lson (id << 1)
#define rson (id << 1 | 1)
const int len;
Tag tag[MAXN << 2];
Info info[MAXN << 2];
SegTree() {}
void update(int id)
{
info[id] = info[lson] + info[rson];
}
void apply(int id, const Tag &v, int l, int r) // 修改id的tag和info
{
info[id].apply(v, l, r);
tag[id].apply(v);
}
void pushdown(int id, int l, int r) // 把id的tag清空,修改左右子的tag和info
{
int mid = (l + r) >> 1;
apply(lson, tag[id], l, mid);
apply(rson, tag[id], mid + 1, r);
tag[id] = Tag(); // 清空tag
}
SegTree(int _len, Info *init): len(_len)
{
std::function<void(int, int, int)> buildtree = [&](int id, int l, int r) // 递归函数,不能用auto
{
if(l == r)
{
info[id] = init[l];
return;
}
int mid = (l + r) >> 1;
buildtree(lson, l, mid), buildtree(rson, mid + 1, r);
update(id);
};
buildtree(1, 1, n);
}
void change(int id, int l, int r, int L, int R, const Tag &v)
{
if(l == L && r == R)
{
apply(id, v, l, r);
return;
}
pushdown(id, l, r);
int mid = (l + r) >> 1;
if(R <= mid) change(lson, l, mid, L, mid, v);
else if(L >= mid + 1) change(rson, mid + 1, r, mid + 1, R, v);
else change(lson, l, mid, L, mid, v), change(rson, mid + 1, r, mid + 1, R, v);
update(id);
}
void change(int L, int R, const Tag &v)
{
change(1, 1, n, L, R, v);
}
Info query(int id, int l, int r, int L, int R)
{
if(l == L && r == R) return info[id];
pushdown(id, l, r);
int mid = (l + r) >> 1;
if(R <= mid) return query(lson, l, mid, L, mid);
else if(L >= mid + 1) return query(rson, mid + 1, r, mid + 1, R);
else return query(lson, l, mid, L, mid) + query(rson, mid + 1, r, mid + 1, R);
}
Info query(int L, int R)
{
return query(1, 1, n, L, R);
}
#undef lson
#undef rson
};
struct Tag
{
i64 c;
Tag() {c = 0;}
Tag(i64 _c): c(_c) {}
void apply(const Tag &rhs) {c += rhs.c;} // Tag的复合
};
struct Info
{
i64 sum;
Info () {}
Info (i64 _sum): sum(_sum) {}
Info operator + (const Info &rhs) {return Info(sum + rhs.sum);}
void apply(const Tag &tag, int l, int r) {sum += 1ll * (r - l + 1) * tag.c;} // 计算tag对info的影响
i64 getans() {return sum;}
}_init[MAXN];
int main()
{
std::cin >> n >> m;
for(int i = 1; i <= n; i++) std::cin >> a[i];
for(int i = 1; i <= n; i++) _init[i] = Info(a[i]);
SegTree<Info, Tag> tr(n, _init);
for(int i = 1, opt, x, y; i <= m; i++)
{
std::cin >> opt >> x >> y;
if(opt == 1)
{
i64 k;
std::cin >> k;
tr.change(x, y, Tag(k));
}
else if(opt == 2) std::cout << tr.query(x, y).getans() << std::endl;
}
return 0;
}
by Grammar__hbw @ 2024-08-30 18:05:51
@DengStar _init
不能被你自己定义,因为编译器会在main函数前面加一个_init函数用来初始化全局变量
by DengStar @ 2024-08-30 18:06:00
好吧我知道了,调试信息中已经说明了,_init
是一个关键字。
我本以为最多 init
是关键字,没想到 _init
也是关键字,逆天了
by DengStar @ 2024-08-30 18:11:11
@Grammar__hbw 好吧,谢谢大佬,我才知道/wul
by CarrotMeow @ 2024-08-30 18:16:22
@DengStar 这好像不算「高度封装」吧。
by IOIer @ 2024-08-30 18:26:25
这貌似不能算高度封装
by DengStar @ 2024-08-30 18:40:38
@CarrotMeow 对于我来说算了/xk 毕竟不是工程代码,到这一步已经足够了