开O2后出错,怀疑有未定义行为

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

tonyre @ 2023-11-16 08:19:20

求助,这份代码不开O2就可以A,问题出在哪里。

鄙人看了很久都没看出来。

#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int MAXN=1e5+5;
struct Tree
{
    int l,r;
    int sum;
    int lazy;
}tree[4*MAXN];
vector<int>to[MAXN];
int a[MAXN];
int son[MAXN],fa[MAXN],siz[MAXN],dep[MAXN];
int tp[MAXN],dfn[MAXN],rnk[MAXN],lst[MAXN];
int cnt;
int n,q,r,mod;
void dfs1(int u,int father)
{
    siz[u]=1;
    for(auto v:to[u])
    {
        if(v==father) continue;
        fa[v]=u,dep[v]=dep[u]+1;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(!son[u]||siz[v]>siz[son[u]]) son[u]=v;
    }
}
void dfs2(int u,int top)
{
    tp[u]=top;
    cnt++;
    dfn[u]=cnt,rnk[cnt]=u;
    if(!son[u]) return lst[u]=dfn[u],void();
    dfs2(son[u],top);
    lst[u]=lst[son[u]];
    for(auto v:to[u])
    {
        if(v==son[u]||v==fa[u]) continue;
        dfs2(v,v);
        lst[u]=max(lst[u],lst[v]);
    }
}
void update(int pos)
{
    tree[pos].sum=(tree[pos<<1].sum+tree[pos<<1|1].sum)%mod;
}
void pushdown(int pos)
{
    tree[pos<<1].sum=(tree[pos<<1].sum+(tree[pos<<1].r-tree[pos<<1].l+1)*tree[pos].lazy)%mod;
    tree[pos<<1|1].sum=(tree[pos<<1|1].sum+(tree[pos<<1|1].r-tree[pos<<1|1].l+1)*tree[pos].lazy)%mod;
    tree[pos<<1].lazy=(tree[pos<<1].lazy+tree[pos].lazy)%mod;
    tree[pos<<1|1].lazy=(tree[pos<<1|1].lazy+tree[pos].lazy)%mod;
    tree[pos].lazy=0;
}
void buildtree(int pos,int l,int r)
{
    tree[pos].l=l,tree[pos].r=r;
    if(l==r) return tree[pos].sum=a[rnk[l]]%mod,void();
    int mid=(l+r)>>1;
    buildtree(pos<<1,l,mid);
    buildtree(pos<<1|1,mid+1,r);
    update(pos);
}
void add(int pos,int s,int t,int x)
{
    if(s<=tree[pos].l&&tree[pos].r<=t)
    {
        tree[pos].sum=(tree[pos].sum+(tree[pos].r-tree[pos].l+1)*x)%mod;
        tree[pos].lazy=(tree[pos].lazy+x)%mod;
        return;
    }
    pushdown(pos);
    int mid=(tree[pos].l+tree[pos].r)>>1;
    if(s<=mid) add(pos<<1,s,t,x);
    if(t>mid) add(pos<<1|1,s,t,x);
    update(pos);
}
int add_path(int u,int v,int x)
{
    while(tp[u]!=tp[v])
    {
        if(dep[tp[u]]<dep[tp[v]]) swap(u,v);
        add(1,dfn[tp[u]],dfn[u],x);
        u=fa[tp[u]];
    }
    add(1,min(dfn[u],dfn[v]),max(dfn[u],dfn[v]),x);
}
int query(int pos,int s,int t)
{
    if(s<=tree[pos].l&&tree[pos].r<=t) return tree[pos].sum;
    pushdown(pos);
    int mid=(tree[pos].l+tree[pos].r)>>1,res=0;
    if(s<=mid) res=(res+query(pos<<1,s,t))%mod;
    if(t>mid) res=(res+query(pos<<1|1,s,t))%mod;
    return res;
}
int query_path(int u,int v)
{
    int res=0;
    while(tp[u]!=tp[v])
    {
        if(dep[tp[u]]<dep[tp[v]]) swap(u,v);
        res=(res+query(1,dfn[tp[u]],dfn[u]))%mod;
        u=fa[tp[u]];
    }
    res=(res+query(1,min(dfn[u],dfn[v]),max(dfn[u],dfn[v])))%mod;
    return res;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("P3384_11.in","r",stdin);
    freopen("P3384.out","w",stdout);
    #endif
    cin>>n>>q>>r>>mod;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        to[u].push_back(v);
        to[v].push_back(u);
    }
    dfs1(r,0);
    dfs2(r,r);
    buildtree(1,1,n);
    for(int i=1;i<=q;i++)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            int u,v,x;
            cin>>u>>v>>x;
            add_path(u,v,x);
        }
        else if(op==2)
        {
            int u,v;
            cin>>u>>v;
            cout<<query_path(u,v)<<endl;
        }
        else if(op==3)
        {
            int u,x;
            cin>>u>>x;
            add(1,dfn[u],lst[u],x);
        }
        else if(op==4)
        {
            int u;
            cin>>u;
            cout<<query(1,dfn[u],lst[u])<<endl;
        }
    }
    return 0;
}

by Buried_Dream @ 2023-11-16 08:23:24

add_path 函数没有返回值


by Buried_Dream @ 2023-11-16 08:24:03

@tonyre add_path 在编译选项里加上 -Wall -std=c++14 -O2 即可发现


by CNS_5t0_0r2 @ 2023-11-16 08:24:28

@Buried_Dream 这个一般不影响(开 O2 后怎么样我就不知道了)


by Buried_Dream @ 2023-11-16 08:24:46

@5t0_0r2 什么玩意不影响,int 函数没返回值


by tonyre @ 2023-11-16 08:25:24

@Buried_Dream 感谢!

我开了 Wall 以为提示的是某个 void 函数无返回值(


by CNS_5t0_0r2 @ 2023-11-16 08:26:00

@Buried_Dream 是的,我之前用过(其他题目)int 函数没返回值照样过。


by Buried_Dream @ 2023-11-16 08:26:30

@5t0_0r2 建议你 Noip 也这样,RE非常好分数


by Buried_Dream @ 2023-11-16 08:27:24

@5t0_0r2 那是因为你没开O2啊,你开了O2就挂了,现在ccf的比赛都开O2


by Read_int @ 2023-11-16 08:30:19

@5t0_0r2 如果你真的认为的话建议你所有比赛都写个 #define void int 吧,我敬你为勇士


by CNS_5t0_0r2 @ 2023-11-16 08:31:42

@Read_int 6,除非是手滑,我**写 int 干嘛


| 下一页