AcWing算法周赛第12场 | 3805环形数组

学习C++从娃娃抓起!记录下AcWing备赛学习过程中的题目,记录每一个瞬间。

附上汇总贴:AcWing算法周赛 |汇总


【题目描述】

给定一个长度为 n n n环形数组 a 0 , a 1 , … , a n − 1 a_0,a_1,\dots,a_{n-1} a0,a1,,an1

现在要对该数组进行 m m m 次操作。

操作分为以下两种:

  • 增值操作 l r d,将区间 [ l , r ] [l,r] [l,r] 上的每个元素都增加 d d d
  • 求最小值操作 l r,输出区间 [ l , r ] [l,r] [l,r] 内的所有元素的最小值。

注意,数组是环形的,所以当 n = 5 n=5 n=5 时,区间 [ 3 , 1 ] [3,1] [3,1] 内的所有元素依次为 a 3 , a 4 , a 0 , a 1 a_3,a_4,a_0,a_1 a3,a4,a0,a1

【输入】

第一行包含整数 n n n,表示数组长度。

第二行包含 n n n 个整数,表示 a 0 , a 1 , … , a n − 1 a_0,a_1,\dots,a_{n-1} a0,a1,,an1

第三行包含整数 m m m,表示操作数。

接下来 m m m 行,每行描述一个操作,对于第 i i i 行,如果包含两个整数 l , r l,r l,r,则表示第 i i i 个操作为求最小值操作;如果包含三个整数 l , r , d l,r,d l,r,d,则表示第 i i i 个操作为增值操作。

【输出】

每个求最小值操作输出一行结果。

【输入样例】

4
1 2 3 4
4
3 0
3 0 -1
0 1
2 1

【输出样例】

1
0
0

【代码详解】

《AcWing 3805 环形数组》 #线段树# #懒标记#

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
const int INF = 1e18;
int n, m; 
int w[N];
struct Node
{
    int l, r;
    int dt, mn;
}tr[N*4];

void pushup(int u)
{
    tr[u].mn = min(tr[u<<1].mn, tr[u<<1|1].mn);
}
void pushdown(int u)
{
    auto &root = tr[u], &l = tr[u<<1], &r = tr[u<<1|1];
    l.dt += root.dt, l.mn += root.dt;
    r.dt += root.dt, r.mn += root.dt;
    root.dt = 0;
}
void build(int u, int l, int r)
{
    if (l==r) tr[u] = {l, r, 0, w[l]};
    else
    {
        tr[u] = {l, r};
        int mid = l+r >> 1;
        build (u<<1, l, mid), build(u<<1|1, mid+1, r);
        pushup(u);
    }
}
void update(int u, int l, int r, int d)
{
    if (tr[u].l>=l && tr[u].r<=r)
    {
        tr[u].dt += d, tr[u].mn += d;
    }
    else 
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l<=mid) update(u<<1, l, r, d);
        if (r>mid) update(u<<1|1, l, r, d);
        pushup(u);
    }
}
int query(int u, int l, int r)
{
    if (tr[u].l>=l && tr[u].r<=r)
    {
        return tr[u].mn;
    }
    else
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        int res = INF;
        if (l<=mid) res = query(u<<1, l, r);
        if (r>mid) res = min(res, query(u<<1|1, l, r));
        return res;
    }
}
signed main()
{
    cin >> n;
    for (int i=0; i<n; i++) cin >> w[i];   
    build(1, 0, n-1);
    cin >> m;
    while (m--)
    {
        int l, r, d;
        char c;
        scanf("%d %d%c", &l, &r, &c);
        if (c=='\n')
        {
            if (l<=r) cout << query(1, l, r) << endl;
            else cout << min(query(1, l, n-1), query(1, 0, r)) << endl;
        }
        else
        {
            cin >> d;
            if (l<=r) update(1, l, r, d);
            else update(1, l, n-1, d), update(1, 0, r, d);
        }
    }
    return 0;
}

【运行结果】

4
1 2 3 4
4
3 0
1
3 0 -1
0 1
0
2 1
0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值