树剖板子RE73pts求调

P3384 【模板】重链剖分/树链剖分

nr0628 @ 2023-07-28 11:46:34

空间都开 2\times10^5 还是 RE。

\texttt{Segmentation fault with invalid memory reference}

代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
#define re register
#define brk break
#define rtn return
#define nxtper next_permutation
#define preper prev_permutation
#define eb emplace_back
#define pb eb
#define ins insert
#define rep(i,a,b) for(re int i(a);i<=b;++i)
#define req(i,a,b) for(re int i(a);i>=b;--i)
#define readf(s) freopen(s,"r",stdin)
#define writef(s) freopen(s,"w",stdout)
inline int read()
{
    re int x=0; re bool f=1; re char ch=getchar();
    while(!isdigit(ch)) f=ch=='-'?0:f,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?x:-x;
}
inline void write(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+48);
}
int n,m,rt,mod,head[400001],nxt[400001],to[400001],cnt;
void add_undirected_edge(int x,int y)
{
    nxt[++cnt]=head[x];
    to[cnt]=y;
    head[x]=cnt;
    nxt[++cnt]=head[y];
    to[cnt]=x;
    head[y]=cnt;
}
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
int w[200001],wew[200001];
namespace segtree
{
    int tree[200001],tag[200001];
    void add_tag(int p,int pl,int pr,int d)
    {
        tag[p]+=d;
        (tree[p]+=d*(pr-pl+1))%=mod;
    }
    void pushup(int p)
    {
        (tree[p]=tree[ls(p)]+tree[rs(p)])%=mod;
    }
    void pushdown(int p,int pl,int pr)
    {
        if(tag[p])
        {
            int mid=pl+pr>>1;
            add_tag(ls(p),pl,mid,tag[p]);
            add_tag(rs(p),mid+1,pr,tag[p]);
            tag[p]=0;
        }
    }
    void build(int p,int pl,int pr)
    {
        tag[p]=0;
        if(pl==pr){(tree[p]=wew[pl])%=mod; rtn;}
        int mid=pl+pr>>1;
        build(ls(p),pl,mid);
        build(rs(p),mid+1,pr);
        pushup(p);
    }
    void update(int l,int r,int p,int pl,int pr,int d)
    {
        if(l<=pl&&pr<=r)
        {
            add_tag(p,pl,pr,d);
            rtn;
        }
        pushdown(p,pl,pr);
        int mid=pl+pr>>1;
        if(l<=mid) update(l,r,ls(p),pl,mid,d);
        if(r>mid) update(l,r,rs(p),mid+1,pr,d);
        pushup(p);
    }
    int query(int l,int r,int p,int pl,int pr)
    {
        if(pl>=l&&r>=pr) return tree[p]%=mod;
        pushdown(p,pl,pr);
        int mid=pl+pr>>1,ans=0;
        if(l<=mid) (ans+=query(l,r,ls(p),pl,mid))%=mod;
        if(r>mid) (ans+=query(l,r,rs(p),mid+1,pr))%=mod;
        return ans%=mod;
    }
}
namespace dividedtree
{
    int num,father[200001],son[200001],depth[200001],siz[200001],top[200001],id[200001];
    void dfs1(int x,int fa)
    {
        depth[x]=depth[fa]+1;
        father[x]=fa;
        siz[x]=1;
        for(int i=head[x];i;i=nxt[i])
            if(to[i]!=fa)
            {
                father[to[i]]=x;
                dfs1(to[i],x);
                siz[x]+=siz[to[i]];
                if(!son[x]||siz[son[x]]<siz[to[i]]) son[x]=to[i];
            }
    }
    void dfs2(int x,int tx)
    {
        id[x]=++num;
        wew[num]=w[x];
        top[x]=tx;
        if(!son[x]) rtn;
        dfs2(son[x],tx);
        for(int i=head[x];i;i=nxt[i])
            if(to[i]!=father[x]&&to[i]!=son[x]) dfs2(to[i],to[i]); 
    }
    void update1(int x,int y,int z)
    {
        while(top[x]!=top[y])
        {
            if(depth[top[x]]<depth[top[y]]) swap(x,y);
            segtree::update(id[top[x]],id[x],1,1,n,z);
            x=father[top[x]];
        }
        if(depth[x]>depth[y]) swap(x,y);
        segtree::update(id[x],id[y],1,1,n,z);
    }
    int query1(int x,int y)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(depth[top[x]]<depth[top[y]]) swap(x,y);
            (ans+=segtree::query(id[top[x]],id[x],1,1,n))%=mod;
            x=father[top[x]];
        }
        if(depth[x]>depth[y]) swap(x,y);
        (ans+=segtree::query(id[x],id[y],1,1,n))%=mod;
        return ans;
    }
    void update2(int x,int k)
    {
        segtree::update(id[x],id[x]+siz[x]-1,1,1,n,k);
    }
    int query2(int x)
    {
        return segtree::query(id[x],id[x]+siz[x]-1,1,1,n)%mod;
    }
}
signed main()
{
    cin>>n>>m>>rt>>mod;
    rep(i,1,n)cin>>w[i];
    rep(i,1,n-1) add_undirected_edge(read(),read());
    dividedtree::dfs1(rt,0);dividedtree::dfs2(rt,rt);
    segtree::build(1,1,n);
    int opt,x,y,z;
    rep(i,1,m)
    {
        cin>>opt>>x;
        switch(opt)
        {
            case 1:cin>>y>>z;dividedtree::update1(x,y,z);brk;
            case 2:cin>>y;cout<<dividedtree::query1(x,y)<<"\n";brk;
            case 3:cin>>y;dividedtree::update2(x,y);brk;
            case 4:cout<<dividedtree::query2(x)<<"\n";brk;
        }
    }
    return 0;
}

by nr0628 @ 2023-07-28 12:06:09

找到了,线段树忘开 4 倍空间


by Genshineer @ 2023-07-28 12:09:37

@nr0628 线段树要开4倍...

要开到 4\times10^5


|