专题测试二 树形结构 A - Circular RMQ

  1. 题目

    You are given circular array a0, a1, ..., an - 1. There are two types of operations with it:

    • inc(lf, rg, v) — this operation increases each element on the segment [lf, rg] (inclusively) by v;
    • rmq(lf, rg) — this operation returns minimal value on the segment [lf, rg] (inclusively).

    Assume segments to be circular, so if n = 5 and lf = 3, rg = 1, it means the index sequence: 3, 4, 0, 1.

    Write program to process given sequence of operations.

    Input

    The first line contains integer n (1 ≤ n ≤ 200000). The next line contains initial state of the array: a0, a1, ..., an - 1 ( - 106 ≤ ai ≤ 106), ai are integer. The third line contains integer m (0 ≤ m ≤ 200000), m — the number of operartons. Next m lines contain one operation each. If line contains two integer lf, rg (0 ≤ lf, rg ≤ n - 1) it means rmq operation, it contains three integers lf, rg, v (0 ≤ lf, rg ≤ n - 1; - 106 ≤ v ≤ 106) — inc operation.

    Output

    For each rmq operation write result for it. Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cout (also you may use %I64d).

    Sample
    Input Output
    4
    1 2 3 4
    4
    3 0
    3 0 -1
    0 1
    2 1
    
    1
    0
    0
    
  2. 思路
    线段树,但是数组是环形的,而且和不少人习惯不一样,数组从0下标开始
    在线段树模板上增加判断,如果l>r的话,就搜l~n-1和0~r的和,否则就正常处理
    要方便的话直接把输入的操作区间全部+1就是从1下标开始了
  3. 代码
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    #define ll long long
    
    ll d[8000000],b[8000000],a[2000005];//区间值,懒惰标记,原始值
    ll n,q;
    
    void build(ll s, ll t, ll p) {
    
    	if (s == t) {
    	    d[p] = a[s];
    	    return;
    	}
    
    	ll m = s + ((t - s) >> 1);
    	build(s, m, p << 1), build(m + 1, t, p << 1 | 1);
    	d[p] =min(d[p << 1], d[(p << 1) + 1]);
    }
    
    void update(ll l, ll r, ll c, ll s, ll t, ll p) {
    
    	if (l <= s && t <= r) {
    		d[p] += c, b[p] += c;
    	    return;
    	}
    
    	ll m = s + ((t - s) >> 1);
    	if (b[p] && s != t) {
    	    d[p << 1] += b[p], d[p << 1 | 1] += b[p];
    		b[p << 1] += b[p], b[p << 1 | 1] += b[p];
    		b[p] = 0;
    	}
    	if (l <= m) update(l, r, c, s, m, p << 1);
    	if (r > m) update(l, r, c, m + 1, t, p << 1 | 1);
    	d[p] = min(d[p << 1], d[p << 1 | 1]);
    }
    
    ll query(ll l, ll r, ll s, ll t, ll p) {
    
    	if (l <= s && t <= r) return d[p];
    
    	ll m = s + ((t - s) >> 1);
    	if (b[p]) {
    	    d[p << 1] += b[p], d[p << 1 | 1] += b[p];
            b[p << 1] += b[p], b[p << 1 | 1] += b[p];
    		b[p] = 0;
    	}
    	ll ans = 10e8;
    	if (l <= m) ans = min(ans,query(l, r, s, m, p << 1));
    	if (r > m) ans = min(ans,query(l, r, m + 1, t, p << 1 | 1));
    	return ans;
    }
    
    int main()
    {
    	cin >> n;
    	for(int i=1;i<=n;i++){
    		cin >> a[i];
    	}
    	build(1,n,1);
    	cin >> q;
    	ll x,y,z;
        while(q--)
        {
            cin >> x >> y;
            x++;y++;//题目数组从0开始
            if(getchar() != '\n')//没换行是三个数
            {
                cin >> z;
                if(x <= y) update(x, y, z, 1, n, 1);
                else
                {
                    update(x, n, z, 1, n, 1);
                    update(1, y, z, 1, n, 1);
                }
            }
            else
            {
                if(x <= y)
    			cout << query(x, y, 1, n, 1) << endl;
                else
    			cout << min(query(x, n, 1, n, 1), query(1, y, 1, n, 1)) << endl;
            }
        }
    }
posted @ 2022-02-07 00:10  Benincasa  阅读(24)  评论(0编辑  收藏  举报