线段树模板
以下为为求区间和,求区间最大值,最小值模板
题目以 敌兵布阵
HDU - 1166 为例子
#include <iostream> #include <algorithm> #include <string.h> #include <cstdio> #include <string> #include <cmath> #include <vector> #include <stack> #include <queue> #include <stack> #include <list> #include <map> #include <set> //#include <unordered_map> #define Fbo friend bool operator < (node a, node b) #define mem(a, b) memset(a, b, sizeof(a)) #define FOR(a, b, c) for (int a = b; a <= c; a++) #define RFOR(a, b, c) for (int a = b; a >= c; a--) #define off ios::sync_with_stdio(0) bool check1(int a) { return (a & (a - 1)) == 0 ? true : false; } using namespace std; typedef pair<int, int> pii; typedef long long ll; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; const int Maxn = 2e5 + 5; const double pi = acos(-1.0); const double eps = 1e-8; ll a[Maxn]; struct node { ll l, r;//区间[l,r] ll add;//区间的延时标记 ll sum;//区间和 int maxn; //区间最大值 int minn; //区间最小值 }tree[Maxn * 4 + 5];//一定要开到4倍多的空间 void pushup(ll rt) { //向上更新 tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum; tree[rt].maxn = max(tree[rt << 1].maxn, tree[rt << 1 | 1].maxn); tree[rt].minn = min(tree[rt << 1].minn, tree[rt << 1 | 1].minn); } void pushdown(ll rt) {//向下更新 if (tree[rt].add) { //若有标记,则讲标记向下移动一层 tree[rt << 1].add += tree[rt].add; tree[rt << 1 | 1].add += tree[rt].add; tree[rt << 1].maxn += tree[rt].add; tree[rt << 1 | 1].maxn += tree[rt].add; tree[rt << 1].minn += tree[rt].add; tree[rt << 1 | 1].minn += tree[rt].add; tree[rt << 1].sum += (tree[rt << 1].r - tree[rt << 1].l + 1) * tree[rt].add; tree[rt << 1 | 1].sum += (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1) * tree[rt].add; tree[rt].add = 0; //取消本层标记 } } void BuildTree(ll l, ll r, ll rt) { tree[rt].l = l; tree[rt].r = r; tree[rt].add = 0;//刚开始一定要清0 tree[rt].sum = r - l + 1; //更新结点rt的值 if (l == r) { //此行根据题意看情况填什么————- tree[rt].sum = a[l]; //———————————————— return; } ll mid = (l + r) >> 1; BuildTree(l, mid, rt << 1); //递归左子树 BuildTree(mid + 1, r, (rt << 1) + 1); //递归右子树 pushup(rt);//向上更新 } void updata(ll l, ll r, ll val, ll rt) { //root为结点 区间更新 // cout << l << " " << tree[rt].l << "----" << r << " " << tree[rt].r << endl; 验证路径 if (l <= tree[rt].l && r >= tree[rt].r) { tree[rt].sum += (tree[rt].r - tree[rt].l + 1) * val; tree[rt].minn += val; //求区间最大值时应改为 tree[rt].minn = val tree[rt].maxn += val; //求区间最小值时应改为 tree[rt].maxn += val tree[rt].add += val;//延时标记 return; } pushdown(rt); ll mid = (tree[rt].l + tree[rt].r) >> 1; if (l <= mid) { updata(l, r, val, rt << 1); } if (r > mid) { updata(l, r, val, rt << 1 | 1); } pushup(rt);//向上更新 } ll querySum(ll l, ll r, ll rt) { //区间求和 if (l <= tree[rt].l && r >= tree[rt].r) { return tree[rt].sum; } pushdown(rt); ll mid = (tree[rt].l + tree[rt].r) >> 1; ll ans = 0; ll Max = 0; ll Min = INF; if (l <= mid) { ans += querySum(l, r, rt << 1); } if (r > mid) { ans += querySum(l, r, rt << 1 | 1); } return ans; } ll queryMin(ll l, ll r, ll rt) { if (l <= tree[rt].l && r >= tree[rt].r) { return tree[rt].minn; } pushdown(rt); ll mid = (tree[rt].l + tree[rt].r) >> 1; ll ans = 0; ll Max = 0; ll Min = INF; if (l <= mid) { Min = min(queryMin(l, r, rt << 1), Min); } if (r > mid) { Min = min(queryMin(l, r, rt << 1 | 1), Min); } return Min; } ll queryMax(ll l, ll r, ll rt) { if (l <= tree[rt].l && r >= tree[rt].r) { return tree[rt].maxn; } pushdown(rt); ll mid = (tree[rt].l + tree[rt].r) >> 1; ll ans = 0; ll Max = 0; ll Min = INF; if (l <= mid) { Max = max(queryMax(l, r, rt << 1), Max); } if (r > mid) { Max = max(queryMax(l, r, rt << 1 | 1), Max); } return Max; } int main() { ll t, n, x, y; scanf("%lld", &t); FOR(i, 1, t) { string s; scanf("%lld", &n); printf("Case %d:\n", i); FOR(j, 1, n)scanf("%d", &a[j]); BuildTree(1, n, 1); while (1) { cin >> s; if (s == "End") break; scanf("%lld%lld", &x, &y); if (s == "Query") cout << querySum(x, y, 1) << endl; if (s == "Add") updata(x, x, y, 1);//[a,a]的元素更新为b if (s == "Sub") updata(x, x, -y, 1); } } return 0; }

浙公网安备 33010602011771号