Codeforces Round #791 (Div. 2) B - Stone Age Problem(懒标记实现区间赋值)

这篇博客详细介绍了如何使用线段树和懒惰传播来处理区间赋值和区间查询的问题。通过给出的代码示例,展示了区间修改和查询的具体实现,包括pushup、pushdown等关键函数,适用于解决动态维护区间数据的问题。
摘要由CSDN通过智能技术生成

题目来源

B Stone Age Problem

点此进入题面

题意:
实现 区间赋值,区间查询

思路:

区间赋值,显然要用到懒标记,即编写 pushdown 函数

区间查询,编写 pushup 函数

具体细节见代码。结合 线段树懒标记的模板

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<bits/stdc++.h>

using namespace std;

//#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef map<int, int> mi;
typedef vector<ll> vll;
typedef pair<ll, ll> pll;
#define pb push_back
#define pp pop_back
#define x first
#define y second
const int N = 2e5 + 10;
int a[N];

struct node
{
    int l, r;
    ll lazy;
    ll sum;
} t[N << 2];

int n, q;

void pushup(int u)
{
    t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
}

void pushdown(int u)
{
    auto& le = t[u << 1], & ri = t[u << 1 | 1], & rt = t[u];
    if (rt.lazy)
    {
        le.lazy = ri.lazy = rt.lazy;
        le.sum = (le.r - le.l + 1) * rt.lazy, ri.sum = (ri.r - ri.l + 1) * rt.lazy;
        rt.lazy = 0;
    }
}

void build(int u, int l, int r)
{
    t[u] = { l, r, 0 };
    if (l == r) { t[u].sum = a[l]; return; }

    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
}

void modify(int u, int l, int r, ll v)
{
    if (t[u].l >= l && t[u].r <= r)
    {
        t[u].sum = (t[u].r - t[u].l + 1) * v;
        t[u].lazy = v;
        return;
    }

    pushdown(u);
    int mid = t[u].l + t[u].r >> 1;
    if (l <= mid) modify(u << 1, l, r, v);
    if (r > mid) modify(u << 1 | 1, l, r, v);
    pushup(u);
}

ll ask(int u, int l, int r)
{
    if (l <= t[u].l && r >= t[u].r) return t[u].sum;

    int mid = t[u].l + t[u].r >> 1;
    ll res = 0;
    if (l <= mid) res += ask(u << 1, l, r);
    if (r > mid) res += ask(u << 1 | 1, l, r);
    return res;
}

signed main()
{
    int T = 1;
    //cin>>T;

    while (T--)
    {
        cin >> n >> q;
        
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);

        build(1, 1, n);

        while (q--)
        {
            int op; scanf("%d", &op);
            if (op == 1)
            {
                int x; ll v; scanf("%d%lld", &x, &v);
                modify(1, x, x, v);
            }
            else
            {
                ll v; scanf("%lld", &v);
                modify(1, 1, n, v);
            }
            printf("%lld\n", ask(1, 1, n));
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值