1. 程式人生 > >codevs 線段樹練習5

codevs 線段樹練習5

pascal sum pan all add int read span body

題目描述 Description

有n個數和5種操作

add a b c:把區間[a,b]內的所有數都增加c

set a b c:把區間[a,b]內的所有數都設為c

sum a b:查詢區間[a,b]的區間和

max a b:查詢區間[a,b]的最大值

min a b:查詢區間[a,b]的最小值

輸入描述 Input Description

第一行兩個整數n,m,第二行n個整數表示這n個數的初始值

接下來m行操作,同題目描述

輸出描述 Output Description

對於所有的sum、max、min詢問,一行輸出一個答案

樣例輸入 Sample Input

10 6

3 9 2 8 1 7 5 0 4 6

add 4 9 4

set 2 6 2

add 3 8 2

sum 2 10

max 1 7

min 3 6

樣例輸出 Sample Output

49

11

4

數據範圍及提示 Data Size & Hint

10%:1<n,m<=10

30%:1<n,m<=10000

100%:1<n,m<=100000

保證中間結果在long long(C/C++)、int64(pascal)範圍內

長代碼看了好理解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
 

using namespace std;
const int N = 1e5 + 10;

#define oo 1423333339
#define LL long long
#define gg 465432477

struct Node{
    LL l, r, w, f, mx, mi, fg;
    
bool qs; }T[N << 2]; LL n, m, answer, maxn, minn; inline LL read() { LL x = 0, f = 1; char c = getchar(); while(c < 0 || c > 9){if(c == -)f = -1;c = getchar();} while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * f; } void imp(LL jd) { T[jd].w = T[jd << 1].w + T[jd << 1 | 1].w; T[jd].mx = max(T[jd << 1].mx, T[jd << 1 | 1].mx); T[jd].mi = min(T[jd << 1].mi, T[jd << 1 | 1].mi); } void down(LL jd) { if(T[jd].qs) { T[jd << 1].f = 0; T[jd << 1].qs = 1; T[jd << 1].fg = T[jd].fg; T[jd << 1].w = (T[jd << 1].r - T[jd << 1].l + 1) * T[jd].fg; T[jd << 1 | 1].f = 0; T[jd << 1 | 1].qs = 1; T[jd << 1 | 1].fg = T[jd].fg; T[jd << 1 | 1].w = (T[jd << 1 | 1].r - T[jd << 1 | 1].l + 1) * T[jd].fg; T[jd << 1].mi = T[jd << 1].mx = T[jd << 1 | 1].mi= T[jd << 1 | 1].mx=T[jd].fg; T[jd].fg = 0; T[jd].qs = 0; } if(T[jd].f) { T[jd << 1].f += T[jd].f; T[jd << 1].w += (T[jd << 1].r - T[jd << 1].l + 1) * T[jd].f; T[jd << 1].mi += T[jd].f; T[jd << 1].mx += T[jd].f; T[jd << 1 | 1].f += T[jd].f; T[jd << 1 | 1].w += (T[jd << 1 | 1].r - T[jd << 1 | 1].l + 1) * T[jd].f; T[jd << 1 | 1].mi += T[jd].f; T[jd << 1 | 1].mx += T[jd].f; T[jd].f = 0; } return ; } void build_tree(LL l, LL r, LL jd) { T[jd].l = l; T[jd].r = r; if(l == r) { T[jd].w = read(); T[jd].mx = T[jd].w; T[jd].mi = T[jd].w; return ; } LL mid = (l + r) >> 1; build_tree(l, mid, jd << 1); build_tree(mid + 1, r, jd << 1 | 1); imp(jd); } void Sec_g(LL l, LL r, LL jd, LL x, LL y, LL yj) { if(x <= l && r <= y) { T[jd].f += yj; T[jd].w += (T[jd].r - T[jd].l + 1) * yj; T[jd].mi += yj; T[jd].mx += yj; return ; } if(T[jd].f || T[jd].qs) down(jd); LL mid = (l + r) >> 1; if(x <= mid) Sec_g(l, mid, jd << 1, x, y, yj); if(y > mid) Sec_g(mid + 1, r, jd << 1 | 1, x, y, yj); imp(jd); } void Sec_set(LL l, LL r, LL jd, LL x, LL y, LL k) { if(x <= l && r <= y) { T[jd].fg = k; T[jd].qs = 1; T[jd].w = (T[jd].r - T[jd].l + 1) * T[jd].fg; T[jd].mx = k; T[jd].mi = k; T[jd].f = 0; return ; } LL mid = (l + r ) >> 1; if(T[jd].f || T[jd].qs) down(jd); if(x <= mid) Sec_set(l, mid, jd << 1, x, y, k); if(y > mid) Sec_set(mid + 1, r, jd << 1 | 1, x, y, k); imp(jd); } void Sec_calc(LL l, LL r, LL jd, LL x, LL y) { if(x <= l && r <= y) { answer += T[jd].w; return; } if(T[jd].f || T[jd].qs) down(jd); LL mid = (l + r) >> 1; if(x <= mid) Sec_calc(l, mid, jd << 1, x, y); if(y > mid) Sec_calc(mid + 1, r, jd << 1 | 1, x, y); } void Sec_min(LL l, LL r, LL jd, LL x, LL y) { if(x <= l && r <= y) { minn = min(minn, T[jd].mi); return ; } if(T[jd].f || T[jd].qs) down(jd); LL mid = (l + r) >> 1; if(x <= mid) Sec_min(l, mid, jd << 1, x, y); if(y > mid) Sec_min(mid + 1, r, jd << 1 | 1, x, y); } void Sec_max(LL l, LL r, LL jd, LL x, LL y) { if(x <= l && r <= y) { maxn = max(maxn, T[jd].mx); return ; } if(T[jd].f || T[jd].qs) down(jd); LL mid = (l + r) >> 1; if(x <= mid) Sec_max(l, mid, jd << 1, x, y); if(y > mid) Sec_max(mid + 1, r, jd << 1 | 1, x, y); } int main() { n = read(); m = read(); build_tree(1, n, 1); for(LL i = 1; i <= m; i ++) { string s; cin >> s; LL x = read(); LL y = read(); if(s == "add") { LL k = read(); Sec_g(1, n, 1, x, y, k); continue; } if(s == "set") { LL k = read(); Sec_set(1, n, 1, x, y, k); continue; } if(s == "sum") { answer = 0; Sec_calc(1, n, 1, x, y); printf("%lld\n", answer); continue; } if(s == "min") { minn = oo; Sec_min(1, n, 1, x, y); printf("%lld\n", minn); continue; } if(s == "max") { maxn = -oo; Sec_max(1, n, 1, x, y); printf("%lld\n", maxn); continue; } } return 0; } /* 10 6 3 9 2 8 1 7 5 0 4 6 add 4 9 4 set 2 6 2 add 3 8 2 sum 2 10 max 1 7 min 3 6 49 11 4 */

codevs 線段樹練習5