社区讨论
如果您 60 RE #1 #2 #3 #6情况6
P3302[SDOI2013] 森林参与者 3已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @lr1eb3du
- 此快照首次捕获于
- 2024/01/06 09:37 2 年前
- 此快照最后确认于
- 2024/01/06 12:30 2 年前
如果您和我的写法类似,都在连边时将小的那棵树 dfs 删除主席树,那么请注意此时可能出现一个点被删除多次的情况。
我的写法:
CPPinline int newnode() {
if(top) {
int x = stk[top--];
return x;
}
else return ++cnt;
}
inline void del(int& o) {
t[o].val = 0;
//注意这里是直接删除,然后放进垃圾桶里的
stk[++top] = o;
o = 0;
}
inline void delnode(int& o) {
if(t[o].ls) delnode(t[o].ls);
if(t[o].rs) delnode(t[o].rs);
del(o);
}
inline void deltree(int u, int f) {
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if(v == f) continue;
deltree(v, u);
}
delnode(root[u]);
}
由于主席树上一个点可能被公用多次,因此可能被删除多次,这样会使后面的更新中发生错误。
因此要记录一下每个点是否已经被删除。如果已经被删除,那就不用放进栈里了。可以用一个 数组实现。
正确写法:
CPPinline int newnode() {
if(top) {
int x = stk[top--];
//
vis[x] = false;
//
return x;
}
else return ++cnt;
}
inline void del(int& o) {
t[o].val = 0;
//注意这里
if(!vis[o]) vis[o] = true, stk[++top] = o;
//
o = 0;
}
inline void delnode(int& o) {
if(t[o].ls) delnode(t[o].ls);
if(t[o].rs) delnode(t[o].rs);
del(o);
}
inline void deltree(int u, int f) {
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if(v == f) continue;
deltree(v, u);
}
delnode(root[u]);
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...