1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned long long ull; 5 #define INF 0X3f3f3f3f 6 const ll MAXN = 2e5 + 7; 7 const ll MOD = 1e9 + 7; 8 ll a[MAXN]; 9 struct node 10 { 11 int left, right; //区间端点 12 ll max, sum; //看题目要求 13 ll lazy; 14 void update(ll x) 15 { 16 sum += (right - left + 1) * x; 17 lazy += x; 18 } 19 } tree[MAXN << 2]; 20 //建树,开四倍 21 void push_up(int x) 22 { 23 tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum; 24 tree[x].max = max(tree[x << 1].max, tree[x << 1 | 1].max); 25 } 26 void push_down(int x) 27 { 28 ll lazeval = tree[x].lazy; 29 if (lazeval) 30 { 31 tree[x << 1].update(lazeval); 32 tree[x << 1 | 1].update(lazeval); 33 tree[x].lazy = 0; 34 } 35 } 36 //若原数组从a[1]~a[n],调用build(1,1,n); 37 void build(int x, int l, int r) 38 { 39 tree[x].left = l; 40 tree[x].right = r; 41 tree[x].sum = tree[x].lazy = 0; 42 if (l == r) //若到达叶节点 43 { 44 tree[x].sum = a[l]; //存储A数组的值 45 tree[x].max = a[l]; 46 } 47 else 48 { 49 int mid = (l + r) / 2; 50 build(x << 1, l, mid); 51 build(x << 1 | 1, mid + 1, r); 52 push_up(x); 53 } 54 return; 55 } 56 //update(1,l,r,v) 57 void update(int x, int l, int r, ll v) //区间更新 58 { 59 int L = tree[x].left, R = tree[x].right; 60 if (l <= L && R <= r) 61 { 62 tree[x].update(v); 63 tree[x].max += v; 64 } 65 else 66 { 67 push_down(x); 68 int mid = (L + R) / 2; 69 if (mid >= l) 70 update(x << 1, l, r, v); 71 if (r > mid) 72 update(x << 1 | 1, l, r, v); 73 push_up(x); 74 } 75 } 76 //单点更新,更新pos点,调用add(1,pos,v) 77 void add(int x, int pos, ll v) //当前更新的节点的编号为id(一般是以1为第一个编号)。pos为需要更新的点的位置,v为修改的值的大小 78 { 79 80 int L = tree[x].left, R = tree[x].right; 81 if (L == pos && R == pos) //左右端点均和pos相等,说明找到了pos所在的叶子节点 82 { 83 tree[x].sum += v; 84 tree[x].max += v; 85 return; //找到了叶子节点就不需要在向下寻找了 86 } 87 int mid = (L + R) / 2; 88 if (pos <= mid) 89 add(x << 1, pos, v); 90 else 91 add(x << 1 | 1, pos, v); //寻找k所在的子区间 92 push_up(x); //向上更新 93 } 94 //调用query_sum(1,l,r)即可查询[l,r]区间内元素的总和 95 //区间查询 96 ll query_sum(int x, int l, int r) 97 { 98 int L = tree[x].left, R = tree[x].right; 99 if (l <= L && R <= r) 100 return tree[x].sum; 101 else 102 { 103 push_down(x); 104 ll ans = 0; 105 int mid = (L + R) / 2; 106 if (mid >= l) 107 ans += query_sum(x << 1, l, r); 108 if (r > mid) 109 ans += query_sum(x << 1 | 1, l, r); 110 push_up(x); 111 return ans; 112 } 113 } 114 //调用query_max(1,l,r)即可求[l,r]区间内元素的最大值 115 ll query_max(int x, int l, int r) 116 { 117 int L = tree[x].left, R = tree[x].right; 118 if (l == L && R == r) 119 return tree[x].max; 120 else 121 { 122 push_down(x); 123 int mid = (L + R) / 2; 124 if (r <= mid) 125 return query_max(x << 1, l, r); 126 else if (l > mid) 127 return query_max(x << 1 | 1, l, r); 128 else 129 return max(query_max(x << 1, l, mid), query_max(x << 1 | 1, mid+1, r)); 130 } 131 } 132 int main() 133 { 134 ll n, m; 135 while (scanf("%lld%lld", &n, &m) != EOF) 136 { 137 for (int i = 1; i <= n; i++) 138 scanf("%lld", &a[i]); 139 build(1, 1, n); 140 getchar(); 141 while (m--) 142 { 143 int l, r; 144 char que; 145 scanf("%c %d %d", &que, &l, &r); 146 getchar(); 147 if (que == 'Q') 148 printf("%lld\n", query_max(1, l, r)); 149 else if (que == 'U') 150 update(1, l,l, r - a[l]),a[l]=r; 151 } 152 } 153 return 0; 154 }
线段树(我的模版)
猜你喜欢
转载自www.cnblogs.com/graytido/p/10745106.html
今日推荐
周排行