学习C++从娃娃抓起!记录下AcWing备赛学习过程中的题目,记录每一个瞬间。
附上汇总贴:AcWing算法周赛 |汇总
【题目描述】
给定一个长度为 n n n 的环形数组 a 0 , a 1 , … , a n − 1 a_0,a_1,\dots,a_{n-1} a0,a1,…,an−1。
现在要对该数组进行 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,…,an−1。
第三行包含整数 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
                
                  
                  
                  
                  
                    
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            