专题测试二 树形结构 A - Circular RMQ
- 题目
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.
InputThe 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.
OutputFor 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
- 思路
线段树,但是数组是环形的,而且和不少人习惯不一样,数组从0下标开始
在线段树模板上增加判断,如果l>r的话,就搜l~n-1和0~r的和,否则就正常处理
要方便的话直接把输入的操作区间全部+1就是从1下标开始了 - 代码
#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; } } }