社区讨论

关于动态开点线段树的空间问题

学术版参与者 5已保存回复 17

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
17 条
当前快照
1 份
快照标识符
@mhz4e0qr
此快照首次捕获于
2025/11/15 01:16
3 个月前
此快照最后确认于
2025/11/16 14:21
3 个月前
查看原帖
这是 CF915E 的代码CPP
#include<bits/stdc++.h>
using namespace std;
const int N=40*(3e5+10); int rt,tot;
struct Node {
    int lc,rc,w,lzy;
    void tag(int x,int len) { w=x*len,lzy=x+1; }
}t[N];
void pushup(int u) { t[u].w=t[t[u].lc].w+t[t[u].rc].w; }
void pushdown(int u,int l,int r) {
    if(!t[u].lzy) return;
    int m=(l+r)>>1;
    if(!t[u].lc) t[u].lc=++tot;
    t[t[u].lc].tag(t[u].lzy-1,m-l+1);
    if(!t[u].rc) t[u].rc=++tot;
    t[t[u].rc].tag(t[u].lzy-1,r-m);
    t[u].lzy=0;
}
void update(int &u,int l,int r,int ul,int ur,int x) {
    //cout<<u<<' '<<l<<' '<<r<<' '<<ul<<' '<<ur<<' '<<x<<'\n';
    if(!u) u=++tot;
    if(ul<=l&&r<=ur) {
        t[u].tag(x,r-l+1);
        return;
    }
    pushdown(u,l,r);
    int m=(l+r)>>1;
    if(ul<=m) update(t[u].lc,l,m,ul,ur,x);
    if(ur>m) update(t[u].rc,m+1,r,ul,ur,x);
    pushup(u);
}
/*int query(int &u,int l,int r,int ql,int qr) {
    if(!u) u=++tot;
    if(ql<=l&&r<=qr) return t[u].w;
    pushdown(u,l,r);
    int m=(l+r)>>1;
    if(qr<=m) return query(t[u].lc,l,m,ql,qr);
    if(ql>m) return query(t[u].rc,m+1,r,ql,qr);
    return query(t[u].lc,l,m,ql,qr)+query(t[u].rc,m+1,r,ql,qr);
}*/
int main() {
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int n,q; cin>>n>>q;
    while(q--) {
        int k,l,r; cin>>l>>r>>k;
        if(k==1) update(rt,1,n,l,r,1);
        else update(rt,1,n,l,r,0);
        cout<<n-t[rt].w<<'\n';
        //cout<<'\n';
        //for(int i=1;i<=20;i++) cout<<i<<' '<<t[i].lc<<' '<<t[i].rc<<' '<<t[i].w<<' '<<t[i].lzy<<'\n';
    }
    return 0;
}
理论上动态开点线段树只要 O(QlogN)O(Q \log N) 的空间。
但第三行的空间定义必须要 40×(3×105+10)40 \times (3 \times 10^5+10) 才够,为什么?
究竟要开多大才行?

回复

17 条回复,欢迎继续交流。

正在加载回复...