题目链接:http://poj.org/problem?id=3468
线段树裸题。。。。
用了两种方法写:
1.lazy,效率略低
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define lowbit(a) ((a)&(-a)) 7 #define max(a, b) ((a)>(b)?(a):(b)) 8 #define min(a, b) ((a)<(b)?(a):(b)) 9 #define MAXN 100100 10 #define PI 3.1415926 11 #define E 2.718281828 12 #define INF 0x777777f 13 typedef long long LL; 14 15 struct tnode{ 16 int lc, rc, l, r; LL data, tag; 17 void clear(){data = tag = lc = rc = 0;} 18 } tree[MAXN*4]; 19 int n, m, tCnt; int a[MAXN]; 20 21 /*根据儿子的信息更新*/ 22 inline void update(tnode &p){ 23 p.data = tree[p.lc].data + tree[p.rc].data; 24 } 25 /*根据父亲的tag更新(注意tag类型)*/ 26 inline void update(tnode &p, LL tag){ 27 p.data += (p.r-p.l+1)*tag; 28 } 29 /*下传tag信息*/ 30 inline void pushdown(tnode &p){ 31 if (!p.tag) return; if (p.l == p.r){p.tag = 0; return;} 32 int mid = (p.l+p.r)>>1; 33 if (p.lc) {tree[p.lc].tag += p.tag; update(tree[p.lc], p.tag);} 34 if (p.rc) {tree[p.rc].tag += p.tag; update(tree[p.rc], p.tag);} 35 p.tag = 0; 36 } 37 /*建树*/ 38 void build(tnode &p, int l, int r){ 39 p.l = l; p.r = r; 40 if (l == r) {p.data = a[l]; return;} 41 int mid = (l+r)>>1; 42 p.lc = ++tCnt; build(tree[p.lc], l, mid); 43 p.rc = ++tCnt; build(tree[p.rc], mid+1, r); 44 update(p); 45 } 46 /*修改*/ 47 void change(tnode &p, int l, int r, int x){ 48 pushdown(p); 49 if (l<=p.l && p.r<=r){p.tag = x; update(p, x); return;} 50 int mid = (p.l+p.r)>>1; 51 if (l <= mid) change(tree[p.lc], l, r, x); 52 if (mid < r) change(tree[p.rc], l, r, x); 53 update(p); 54 } 55 /*查询(注意返回类型)*/ 56 LL query(tnode &p, int l, int r){ 57 pushdown(p); 58 if (l<=p.l && p.r<=r) {return p.data;} 59 int mid = (p.l+p.r)>>1; LL ret = 0; 60 if (l <= mid) ret += query(tree[p.lc], l, r); 61 if (mid < r) ret += query(tree[p.rc], l, r); 62 return ret; 63 } 64 int main(){ 65 scanf("%d%d", &n, &m); 66 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 67 tCnt = 1; build(tree[1], 1, n); 68 char c = getchar(); int l, r, x; 69 for (int i = 1; i <= m; i++){ 70 c = getchar(); 71 if (c=='C'){ 72 scanf("%d%d%d", &l, &r, &x); 73 change(tree[1], l, r, x); 74 } 75 else { 76 scanf("%d%d", &l, &r); 77 printf("%I64d\n", query(tree[1], l, r)); 78 } 79 getchar(); 80 } 81 return 0; 82 }
2.标记永久化,效率较高
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define lowbit(a) ((a)&(-a)) 7 #define max(a, b) ((a)>(b)?(a):(b)) 8 #define min(a, b) ((a)<(b)?(a):(b)) 9 #define MAXN 100100 10 #define PI 3.1415926 11 #define E 2.718281828 12 #define INF 0x777777f 13 typedef long long LL; 14 15 struct tnode{ 16 int lc, rc, l, r; LL data, tag; 17 void clear(){data = tag = lc = rc = 0;} 18 } tree[MAXN*4]; 19 int n, m, tCnt; int a[MAXN]; 20 21 /*建树*/ 22 void build(tnode &p, int l, int r){ 23 p.l = l; p.r = r; 24 if (l == r) {p.data = a[l]; return;} 25 int mid = (l+r)>>1; 26 p.lc = ++tCnt; build(tree[p.lc], l, mid); 27 p.rc = ++tCnt; build(tree[p.rc], mid+1, r); 28 /*update_p*/ 29 p.data = tree[p.lc].data+tree[p.rc].data; 30 /*update_p*/ 31 } 32 /*修改(l、r都在p的范围内)*/ 33 void change(tnode &p, int l, int r, int v){ 34 /*update_p*/ 35 p.data += (r-l+1)*v; 36 if (l==p.l && p.r==r) {p.tag += v; return;} 37 /*update_p*/ 38 int mid = (p.l+p.r)>>1; 39 if (r <= mid) {change(tree[p.lc], l, r, v); return;} //全在左子树 40 if (l > mid) {change(tree[p.rc], l, r, v); return;} //全在右子树 41 change(tree[p.lc], l, mid, v); change(tree[p.rc], mid+1, r, v); //越过中点 42 } 43 /*查询(注意返回类型,其他同上)*/ 44 LL query(tnode &p, int l, int r){ 45 if (l==p.l && p.r==r) {return p.data;} 46 int mid = (p.l+p.r)>>1; LL ret = (r-l+1)*p.tag; 47 if (r <= mid) return ret+query(tree[p.lc], l, r); 48 if (l > mid) return ret+query(tree[p.rc], l, r); 49 return ret+query(tree[p.lc], l, mid)+query(tree[p.rc], mid+1, r); 50 } 51 int main(){ 52 scanf("%d%d", &n, &m); 53 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 54 tCnt = 1; build(tree[1], 1, n); 55 char c = getchar(); int l, r, x; 56 for (int i = 1; i <= m; i++){ 57 c = getchar(); 58 if (c=='C'){ 59 scanf("%d%d%d", &l, &r, &x); 60 change(tree[1], l, r, x); 61 } 62 else { 63 scanf("%d%d", &l, &r); 64 printf("%I64d\n", query(tree[1], l, r)); 65 } 66 getchar(); 67 } 68 return 0; 69 }