30pt求调,代码注释详细(
查看原帖
30pt求调,代码注释详细(
637788
kimi0705楼主2024/8/18 11:18
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 300005;
const int mod = 1e18 + 7;
int arr[MAXN];
int minTree[4 * MAXN];
int sumSquareTree[4 * MAXN];
int n, cnt, q, op, l, r, k, x;

// 构建线段树
void build(int node, int start, int end) {
    if (start == end) {
        // 叶节点
        minTree[node] = arr[start];
        sumSquareTree[node] = (1LL * arr[start] * arr[start]) % mod;
    } else {
        int mid = (start + end) / 2;
        int leftChild = 2 * node;
        int rightChild = 2 * node + 1;

        build(leftChild, start, mid);
        build(rightChild, mid + 1, end);

        // 内部节点
        minTree[node] = min(minTree[leftChild], minTree[rightChild]);
        sumSquareTree[node] = (sumSquareTree[leftChild] + sumSquareTree[rightChild]) % mod;
    }
}

// 区间最小值查询
int queryMin(int node, int start, int end, int L, int R) {
    if (R < start || L > end) {
        // 查询区间在当前节点区间之外
        return LLONG_MAX / 2;
    }

    if (L <= start && end <= R) {
        // 当前节点的区间完全在查询区间内
        return minTree[node];
    }

    // 查询左右子区间
    int mid = (start + end) / 2;
    int leftChild = 2 * node;
    int rightChild = 2 * node + 1;

    int leftMin = queryMin(leftChild, start, mid, L, R);
    int rightMin = queryMin(rightChild, mid + 1, end, L, R);

    return min(leftMin, rightMin);
}

// 区间平方和查询
long long querySumSquare(int node, int start, int end, int L, int R) {
    if (R < start || L > end) {
        // 查询区间在当前节点区间之外
        return 0;
    }

    if (L <= start && end <= R) {
        // 当前节点的区间完全在查询区间内
        return sumSquareTree[node];
    }

    // 查询左右子区间
    int mid = (start + end) / 2;
    int leftChild = 2 * node;
    int rightChild = 2 * node + 1;

    long long leftSumSquare = querySumSquare(leftChild, start, mid, L, R);
    long long rightSumSquare = querySumSquare(rightChild, mid + 1, end, L, R);

    return (leftSumSquare + rightSumSquare) % mod;
}

// 单点更新
void update(int node, int start, int end, int idx, int value) {
    if (start == end) {
        // 叶节点更新
        arr[idx] = value;
        minTree[node] = value;
        sumSquareTree[node] = (1LL * value * value) % mod;
    } else {
        int mid = (start + end) / 2;
        int leftChild = 2 * node;
        int rightChild = 2 * node + 1;

        if (start <= idx && idx <= mid) {
            update(leftChild, start, mid, idx, value);
        } else {
            update(rightChild, mid + 1, end, idx, value);
        }

        // 更新内部节点
        minTree[node] = min(minTree[leftChild], minTree[rightChild]);
        sumSquareTree[node] = (sumSquareTree[leftChild] + sumSquareTree[rightChild]) % mod;
    }
}

int calc (int l, int r, int k) {
    int a = r - l;
    int b = r - l + 1; 
    int x = queryMin(1, 1, n, l, r);
    return (b * x * x % mod + x * k * a * b % mod + k * k * (a * b * (a + b) / 6 % mod) % mod) % mod; 
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> q;
    for (int i = 1; i <= n; i++) cin >> arr[i];
    build(1, 1, n);
    while (q--) {
        cin >> op;
        if (op == 1) cin >> x >> k, x ^= cnt, k ^= cnt;
        if (op == 2) cin >> l >> r >> k, l ^= cnt, r ^= cnt, k ^= cnt;
        if (op == 1) { update(1, 1, n, x, k); }
        if (op == 2) {
            bool ok = querySumSquare(1, 1, n, l, r) == calc (l, r, k);
            cnt += ok;
            cout << (ok ? "Yes" : "No") << '\n';
        }
    }
    return 0;
}
2024/8/18 11:18
加载中...