关于函数返回值

P4513 小白逛公园

Kevinx @ 2024-10-12 20:04:02

本人这题卡了两个月,最后被老师发现是函数返回值导致我RE和MLE,请问有人能解释一下是什么原因导致的吗?

程序第13行:

改之前:

ll pushup(ll p)

改成这个就ac了

void pushup(ll p)

所以一个定义了有返回值的函数但是不return会有什么影响?


by _Supernova @ 2024-10-12 20:06:17

请发完整代码。


by 大眼仔Happy @ 2024-10-12 20:07:26

ub 了解一下


by Estrella_Explore @ 2024-10-12 20:07:50

如果你启用较为严格的编译选项,你会获得类似于以下的警告:

./test.cpp: In function ‘long long int test()’:
./test.cpp:4:45: 警告:在有返回值的函数中未发现 return 语句 [-Wreturn-type]
    4 | long long test() { cout << "Hello, world!"; }
      |                                             
#include <iostream>
using namespace std;

long long test() { cout << "Hello, world!"; }

int main() {
    test();
    return 0;
}

by Kevinx @ 2024-10-12 20:12:34

@_Supernova

RE+TLE

#include<bits/stdc++.h>
#define ll int
#define Mid ll mid = (l+r)>>1
using namespace std;
bool st;
const ll N =  5e5 + 20;
ll n, m, a[N], cnt = 0;
struct segtree{
    ll maxv, maxl, maxr, sum;
}tree[N<<2];
ll ls(ll x) {return x<<1;}
ll rs(ll x) {return x<<1|1;}
ll pushup(ll p) {
    tree[p].sum = tree[ls(p)].sum + tree[rs(p)].sum;
    tree[p].maxl = max(tree[ls(p)].maxl, tree[ls(p)].sum+tree[rs(p)].maxl);
    tree[p].maxr = max(tree[rs(p)].maxr, tree[rs(p)].sum+tree[ls(p)].maxr);
    ll k1 = tree[ls(p)].maxr, k2 =  tree[rs(p)].maxl;
    ll K = max(max(k1, k2), k1+k2);
    tree[p].maxv = max(max(tree[ls(p)].maxv, tree[rs(p)].maxv), K);
}

void build(ll p, ll l, ll r) {
    if(l == r) {
        tree[p].maxl = tree[p].maxr = tree[p].maxv = tree[p].sum = a[l];
        return; 
    }
    Mid;
    build(ls(p), l, mid);
    build(rs(p), mid+1, r);
    pushup(p);
    return ;
}
void change(ll p, ll l, ll r, ll x, ll k) {
    Mid;
    if(l == r) {
        tree[p].maxl = tree[p].maxr = tree[p].maxv = tree[p].sum = k;
        return ;
    }

    if(x <= mid) change(ls(p), l, mid, x, k);
    if(x >  mid) change(rs(p), mid+1, r, x, k);
    pushup(p);
    return ;
}
segtree query(ll p, ll l, ll r, ll x, ll y) {
    if(x <= l && r <= y) {
        return tree[p];
    }
    Mid;
    segtree A = {0, 0, 0, 0}, B = {0, 0, 0, 0}, C1 = {0, 0, 0, 0};
    bool vis1=0,vis2=0;
    if(x <= mid) A = query(ls(p), l, mid, x, y), vis1 = 1;
    if(y >  mid) B = query(rs(p), mid+1, r, x, y), vis2 = 1;
    if(vis1 == 1 && vis2 == 0) return A;
    else if(vis1 == 0 && vis2 == 1) return B;
    else {
    C1.sum = A.sum + B.sum;
    C1.maxl = max(A.maxl, A.sum+B.maxl);
    C1.maxr = max(B.maxr, B.sum+A.maxr);
    ll k1 = A.maxr, k2 =  B.maxl;
    ll K = max(max(k1, k2), k1+k2);
    C1.maxv = max(max(A.maxv, B.maxv), K);
    }
    return C1;
}
bool ed;
int main(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    build(1, 1, n);
    segtree ans;
    for(int i = 1; i <= m; i++) {
        ll op, x, y;
        cin >> op >> x >> y;
        if(op == 2) {
//          if(x>y) swap(x, y);
            change(1, 1, n, x, y);
        }
        else{
            if(x>y) swap(x, y);
            ans = query(1, 1, n, x, y);
            cout << ans.maxv << endl;
        }
    }
    return 0;
}
/*
5 3
1
2
-3
4
5
1 4 5

*/

AC:

#include<bits/stdc++.h>
#define ll int
#define Mid ll mid = (l+r)>>1
using namespace std;
bool st;
const ll N =  5e5 + 20;
ll n, m, a[N], cnt = 0;
struct segtree{
    ll maxv, maxl, maxr, sum;
}tree[N<<2];
ll ls(ll x) {return x<<1;}
ll rs(ll x) {return x<<1|1;}
void pushup(ll p) {
    tree[p].sum = tree[ls(p)].sum + tree[rs(p)].sum;
    tree[p].maxl = max(tree[ls(p)].maxl, tree[ls(p)].sum+tree[rs(p)].maxl);
    tree[p].maxr = max(tree[rs(p)].maxr, tree[rs(p)].sum+tree[ls(p)].maxr);
    ll k1 = tree[ls(p)].maxr, k2 =  tree[rs(p)].maxl;
    ll K = max(max(k1, k2), k1+k2);
    tree[p].maxv = max(max(tree[ls(p)].maxv, tree[rs(p)].maxv), K);
}

void build(ll p, ll l, ll r) {
    if(l == r) {
        tree[p].maxl = tree[p].maxr = tree[p].maxv = tree[p].sum = a[l];
        return; 
    }
    Mid;
    build(ls(p), l, mid);
    build(rs(p), mid+1, r);
    pushup(p);
    return ;
}
void change(ll p, ll l, ll r, ll x, ll k) {
    Mid;
    if(l == r) {
        tree[p].maxl = tree[p].maxr = tree[p].maxv = tree[p].sum = k;
        return ;
    }

    if(x <= mid) change(ls(p), l, mid, x, k);
    if(x >  mid) change(rs(p), mid+1, r, x, k);
    pushup(p);
    return ;
}
segtree query(ll p, ll l, ll r, ll x, ll y) {
    if(x <= l && r <= y) {
        return tree[p];
    }
    Mid;
    segtree A = {0, 0, 0, 0}, B = {0, 0, 0, 0}, C1 = {0, 0, 0, 0};
    bool vis1=0,vis2=0;
    if(x <= mid) A = query(ls(p), l, mid, x, y), vis1 = 1;
    if(y >  mid) B = query(rs(p), mid+1, r, x, y), vis2 = 1;
    if(vis1 == 1 && vis2 == 0) return A;
    else if(vis1 == 0 && vis2 == 1) return B;
    else {
    C1.sum = A.sum + B.sum;
    C1.maxl = max(A.maxl, A.sum+B.maxl);
    C1.maxr = max(B.maxr, B.sum+A.maxr);
    ll k1 = A.maxr, k2 =  B.maxl;
    ll K = max(max(k1, k2), k1+k2);
    C1.maxv = max(max(A.maxv, B.maxv), K);
    }
    return C1;
}
bool ed;
int main(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    build(1, 1, n);
    segtree ans;
    for(int i = 1; i <= m; i++) {
        ll op, x, y;
        cin >> op >> x >> y;
        if(op == 2) {
            change(1, 1, n, x, y);
        }
        else{
            if(x>y) swap(x, y);
            ans = query(1, 1, n, x, y);
            cout << ans.maxv << endl;
        }
    }
    return 0;
}
/*
5 3
1
2
-3
4
5
1 4 5

*/

by exploration @ 2024-10-12 20:13:35

@Kevinx 定义了有返回值的函数但不写return语句会导致函数默认返回None,那么就会RE


by Kevinx @ 2024-10-12 20:26:06

@_Supernova @大眼仔Happy @Estrella_Explore @exploration 感谢


by Terrible @ 2024-10-12 20:30:10

具体原因:非 void 函数执行时没有返回值,则洛谷 GCC 编译出的汇编对应位置没有 ret 从而执行时代码串行,从而可能出各种错误,当然也可能莫名其妙没有问题。

开 O2 时串行出错的概率更大,不开 O2 时有可能会编译出来一个 ret 从而防范了出错,但是不能保证一定有 ret。

规范上,应当给所有 非 void 函数的所有可访问的情况都设定 return。核心要求是程序完整执行的时候函数必须 return,而并非要求这个函数对任意输入都必须有明确返回值。


by Kevinx @ 2024-10-12 20:36:55

@Terrible 拜谢dalao


|