MnZn 刚学线段树求助,为什么样例过不了?

P3372 【模板】线段树 1

CarrotMeow @ 2023-04-17 17:25:45

rt,提交上去 2xWA + 8xRE qwq

#include <bits/stdc++.h>
using namespace std;

namespace newstd {
#define fo(i,a,b) for (auto i = a; i < b; i++)
#define foe(i,a,b) for (auto i = a; i <= b; i++)
#define of(i,b,a) for (auto i = b; i > a; i--)
#define ofe(i,b,a) for (auto i = b; i >= a; i--)
#define fi(i,s) for (auto i : s)
#define print(fmt, ...) printf(fmt, __VA_ARGS__), printf("\n") 
#define sq(x) ((x) * (x))
#define cb(x) (sq(x) * (x))
#define ks(s) (string(s))
#define ts(s) (to_string(s))
#define mem(s, a) memset(s, a, sizeof(s))
#define v1 first
#define v2 second

typedef const ssize_t constant;
typedef long long ll;
typedef __int128 lll;
typedef unsigned ui;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef pair<int, int> pii;

const int inf = 0x3f3f3f3f;
const ll inf_ll = 0x3f3f3f3f3f3f3f3fll;
constant _FREAD_SIZE = 0x10000;
char buf[_FREAD_SIZE], *p1 = buf, *p2 = buf;

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, _FREAD_SIZE, stdin), p1 == p2) ? EOF: *p1++)

template<class _Tp, constant __len> 
using arr = _Tp [__len];
template<class _Tp, constant __len, constant __len2> 
using arr2 = _Tp [__len][__len2];
template<class _Tp = ll>
inline _Tp read() {
    char c = getchar();
    _Tp x = 0;
    int f = 1;
    for(; !isdigit(c); c = getchar())
        if (c == '-') f *= -1;
    for(; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c - 48);
    return x * f;
}
template<class _Tp>
inline void read(_Tp &x) {
    x = read<_Tp>();
}
template<class _Tp, class ..._Up>
inline void read(_Tp &x, _Up &...__args) {
    read(x), read(__args...);
}
template<class _Tp> 
inline _Tp gcd(_Tp n, _Tp m) {return m ? gcd(m, n % m) : n;}
template<class _Tp>
inline _Tp lcm(_Tp n, _Tp m) {return n / gcd(n, m) * m;}
} // namespace
using namespace newstd;
/* =================== */

constant N = 1e5 + 10;
ll a[N], w[N << 2], z[N << 2];

void pushup(const int u) {
    w[u] = w[u << 1] + w[(u << 1) + 1];
}

void build(const int u, int l, int r) {
    if (l == r) {
        w[u] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(u << 1, l, mid);
    build((u << 1) + 1, mid + 1, r);
    pushup(u);
}

ll query1(int u, int l, int r, int p) {
    if (l == r)
        return w[u];
    else {
        int mid = (l + r) >> 1;
        if (mid >= p)
            return query1(u << 1, l, mid, p);
        else
            return query1((u << 1) + 1, mid + 1, r, p);
    }
}

void update1(int u, int l, int r, int p, ll x) {
    if (l == r)
        w[u] = x;
    else {
        int mid = (l + r) >> 1;
        if (mid >= p)
            update1(u << 1, l, mid, p, x);
        else
            update1((u << 1) + 1, mid + 1, r, p, x);
        pushup(u);
    }
}

bool inrange(int l, int r, int l2, int r2) {
    return (l <= l2) && (r <= r2);
}

bool outrange(int l, int r, int l2, int r2) {
    return (l > r2) || (r < l2);
}

void maketag(int u, int l, ll x) {
    z[u] += x;
    w[u] += l * x;
}

void pushdown(int u, int l, int r) {
    int mid = (l + r) >> 1;
    maketag(u << 1, mid - l + 1, z[u]);
    maketag((u << 1) + 1, r - mid, z[u]);
    z[u] = 0;
}

ll query(int u, int l, int r, int l2, int r2) {
    if (inrange(l, r, l2, r2))
        return w[u];
    else if (!outrange(l, r, l2, r2)) {
        int mid = (l + r) >> 1;
        pushdown(u, l, r);
        return query(u << 1, l, mid, l2, r2)
            + query((u << 1) + 1, mid + 1, r, l2, r2);
    } else return 0;
}

void update(int u, int l, int r, int l2, int r2, ll x) {
    if (inrange(l, r, l2, r2))
        maketag(u, r - l + 1, x);
    else if (!outrange(l, r, l2, r2)) {
        int mid = (l + r) >> 1;
        pushdown(u, l, r);
        update(u << 1, l, mid, l2, r2, x);
        update((u << 1) + 1, mid + 1, r, l2, r2, x);
        pushup(u);
    }
}

signed main() {
    int n = read(), m = read();
    foe (i, 1, n)
        read(a[i]);
    build(1, 1, n);
    foe (i, 1, m) {
        if (read() == 1)
            update(1, 1, n, read(), read(), read());
        else
            print("%lld", query(1, 1, n, read(), read()));
    }
}

by H_Kaguya @ 2023-04-17 17:49:59

一方面,inrange 函数有误。
另一方面,update(1, 1, n, read(), read(), read()); 这种东西属于 UB。


by CarrotMeow @ 2023-04-17 21:18:22

@H_Kaguya

另一方面,update(1, 1, n, read(), read(), read()); 这种东西属于 UB。

为什么呀?这边不行吗,还是传输的数据会出错


by CarrotMeow @ 2023-04-17 21:21:57

悲催记录 https://www.luogu.com.cn/record/108369431 是 UB 的问题吗


by H_Kaguya @ 2023-04-17 21:25:37

改成

int x = read(), y = read(), c = read();
update(1, 1, n, x, y, c);

就对了。
(包括下面的 print 也要改)
具体的,C++ 并未规定 函数参数的调用顺序。
实际上参数是压到栈里的,也就是说这里的 read() 函数会反着调用。


by CarrotMeow @ 2023-04-17 21:42:17

@H_Kaguya 已关注

Oh... 已 A,帖结


|