社区讨论

不会就我线段树+二分炸了吧?

P11217【MX-S4-T1】「yyOI R2」youyou 的垃圾桶参与者 5已保存回复 12

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
12 条
当前快照
1 份
快照标识符
@m2hj8x3n
此快照首次捕获于
2024/10/20 19:57
去年
此快照最后确认于
2025/11/04 23:50
4 个月前
查看原帖
调了一个半小时,炸了
代码:
CPP
#include<bits/stdc++.h>

using namespace std;
int n, q, W;
int a[200010], sum[800010], lazy[800010];

void build(int l, int r, int fa) {
    if (l == r) {
        sum[fa] = a[l];
        return;
    } else {
        int m = l + ((r - l) >> 1);;
        build(l, m, fa << 1);
        build(m + 1, r, fa << 1 | 1);
        sum[fa] = sum[fa << 1] + sum[fa << 1 | 1];
        return;
    }
}

int query(int l, int r, int s, int t, int fa) {//[l,r] now,[s,t] change,fa = father
    if (s <= l && t >= r) return sum[fa];
    else {
        int m = l + ((r - l) >> 1), s1, s2;
        if (lazy[fa]) {
            lazy[fa << 1] += lazy[fa], sum[fa << 1] += lazy[fa] * (m - l + 1);
            lazy[fa << 1 | 1] += lazy[fa], sum[fa << 1 | 1] += lazy[fa] * (r - m);
        }
        if (s <= m) s1 = query(l, m, s, t, fa << 1);
        if (t > m) s2 = query(m + 1, r, s, t, fa << 1 | 1);
        return s1 + s2;
    }
}

void update(int l, int r, int fa, int num, int s, int t) {//[l,r] now,[s,t] change,num = change now,fa = father
    if (s <= l && t >= r) {
        sum[fa] += (r - l + 1) * num, lazy[fa] += num;
        return;
    } else {
        int m = l + ((r - l) >> 1);
        if (lazy[fa] && l != r) {
            lazy[fa << 1] += lazy[fa], sum[fa << 1] += (m - l + 1) * lazy[fa];
            lazy[fa << 1 | 1] += lazy[fa], sum[fa << 1 | 1] += (r - m) * lazy[fa];
            lazy[fa] = 0;
        }
        if (s <= m) update(l, m, fa << 1, num, s, t);
        if (t > m) update(m + 1, r, fa << 1 | 1, num, s, t);
        sum[fa] = sum[fa << 1] + sum[fa << 1 | 1];
        return;
    }
}

long long quick_pow(int a, int b) {
    long long res = 1;
    while (b) {
        if (b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

int main() {
    cin >> n >> q >> W;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    int x = W;
    build(1, n, 1);
    for (int i = 1; i <= q; i++) {
        int l, r, d;
        cin >> l >> r >> d;
        update(1, n, 1, d, l, r);
        int snum = query(1, n, 1, n, 1);
        int ans = 0, cnt = 0;
        int ll = 0, rr = x / snum;
        while (ll < rr) {
            int mm = (ll + rr) >> 1;
            cout << ll << " " << rr << " " << mm << "\n";
            if ((quick_pow(2, mm) - 1) * snum < x) ll = mm + 1, cnt = ll;
            else rr = mm - 1;
        }
        int lll = cnt;
        ans = ll * n;
        cnt = 0;
        x -= (quick_pow(2, lll) - 1) * snum;
        cout << x << "\n";
        ll = 0, rr = n;
        while (ll < rr) {
            int mm = (ll + rr) >> 1;
            cout << ll << " " << rr << " " << mm << "\n";
            if (query(1, n, 1, mm, 1) * quick_pow(2, lll + 1) < x)
                l = mm + 1, cnt = mm, cout << query(1, n, 1, mm, 1) << "\n";
            else r = mm - 1;
        }
        cout << ans + cnt << "\n";
        x = W;
    }
}
/*
6 4 75
9 1 4 5 1 4
1 1 1
3 5 3
3 5 1
3 5 3
ans:
11
9
8
8
*/
有大神说正解 O(n)O(n),但是我就是个学了9个月的小蒟蒻,就写了一个线段树+二分,时间复杂度 O(n(logn)2)O(n (\log n)^2),帮调,互关

回复

12 条回复,欢迎继续交流。

正在加载回复...