牛客練習賽 資料結構 線段樹
阿新 • • 發佈:2018-11-03
連結:https://www.nowcoder.com/acm/contest/200/B
來源:牛客網
qn姐姐最好了~
qn姐姐給你了一個長度為n的序列還有m次操作讓你玩,
1 l r 詢問區間[l,r]內的元素和
2 l r 詢問區間[l,r]內的元素的平方 和
3 l r x 將區間[l,r]內的每一個元素都乘上x
4 l r x 將區間[l,r]內的每一個元素都加上x
輸入描述:
第一行兩個數n,m 接下來一行n個數表示初始序列 就下來m行每行第一個數為操作方法opt, 若opt=1或者opt=2,則之後跟著兩個數為l,r 若opt=3或者opt=4,則之後跟著三個數為l,r,x 操作意思為題目描述裡說的
輸出描述:
對於每一個操作1,2,輸出一行表示答案
示例1
輸入
5 6
1 2 3 4 5
1 1 5
2 1 5
3 1 2 1
4 1 3 2
1 1 4
2 2 3
輸出
15
55
16
41
線段樹懶惰標記:
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; #define ll long long const int maxm = 10005; int a[maxm]; struct node { ll val, sb, sc, l, r, s2; ll add, mdd; }tr[maxm * 20]; void down(int num) { int l = tr[num].l, r = tr[num].r; ll add = tr[num].add, mdd = tr[num].mdd; if (add) { tr[num].s2 += 2 * tr[num].val*add + (r - l + 1)*add*add; tr[num].val += add*(r - l + 1); if (tr[num].l != tr[num].r) { down(num * 2), down(num * 2 + 1); tr[num * 2].add = tr[num * 2 + 1].add = add; } tr[num].add = 0; } if (mdd > 1) { tr[num].val *= mdd; tr[num].s2 *= (mdd*mdd); if (tr[num].l != tr[num].r) { down(num * 2), down(num * 2 + 1); tr[num * 2].mdd = tr[num * 2 + 1].mdd = tr[num].mdd; } tr[num].mdd = 1; } } void build(int l, int r, int num) { tr[num].l = l, tr[num].r = r; tr[num].add = 0, tr[num].mdd = 1; if (l == r) { tr[num].val = a[l]; tr[num].s2 = a[l] * a[l]; tr[num].sb = tr[num].sc = 0; tr[num].add = 0, tr[num].mdd = 1; return; } int mid = (l + r) / 2; build(l, mid, num * 2); build(mid + 1, r, num * 2 + 1); tr[num].val = tr[num * 2].val + tr[num * 2 + 1].val; tr[num].s2 = tr[num * 2].s2 + tr[num * 2 + 1].s2; } void update(int l, int r, ll val, int num, int flag) { if (tr[num].add || tr[num].mdd > 1) down(num); if (l == tr[num].l&&r == tr[num].r) { if (flag == 1) tr[num].add += val; else tr[num].mdd *= val; down(num); return; } int mid = (tr[num].l + tr[num].r) / 2; if (mid >= r) update(l, r, val, num * 2, flag); else if (mid < l) update(l, r, val, num * 2 + 1, flag); else { update(l, mid, val, num * 2, flag); update(mid + 1, r, val, num * 2 + 1, flag); } down(num * 2), down(num * 2 + 1); tr[num].val = tr[num * 2].val + tr[num * 2 + 1].val; tr[num].s2 = tr[num * 2].s2 + tr[num * 2 + 1].s2; } ll query(int l, int r, int num, int flag) { if (tr[num].add || tr[num].mdd > 1) down(num); if (tr[num].l >= l&&tr[num].r <= r) { if (flag == 1) return tr[num].val; else return tr[num].s2; } int mid = (tr[num].l + tr[num].r) / 2; ll ans = 0; if (mid >= r) ans += query(l, r, num * 2, flag); else if (mid < l) ans += query(l, r, num * 2 + 1, flag); else { ans += query(l, mid, num * 2, flag); ans += query(mid + 1, r, num * 2 + 1, flag); } return ans; } int main() { int n, i, j, k, sum, m, flag, l, r, x; scanf("%d%d", &n, &m); for (i = 1;i <= n;i++) scanf("%d", &a[i]); build(1, n, 1); while (m--) { scanf("%d%d%d", &flag, &l, &r); if (flag == 1 || flag == 2) printf("%lld\n", query(l, r, 1, flag)); else { scanf("%d", &x); if (flag == 3) update(l, r, x, 1, 2); else update(l, r, x, 1, 1); } } return 0; }