线段树
Posted SteveDevin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树相关的知识,希望对你有一定的参考价值。
1.数组大小为Max << 2; 2.初始化 #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 3.建树 void build(int l, int r, int rt) { if (l == r) { scanf("%d", &sum[rt]); return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } 4.更新节点 void update(int p, int add, int l, int r, int rt) { if (l == r) { sum[rt] += add; return ; } int m = (l + r) >> 1; if (p <= m) update(p , add , lson); else update(p , add , rson); PushUP(rt); } 5.区间求和 int query(int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { return sum[rt]; } int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += query(L , R , lson); if (R > m) ret += query(L , R , rson); return ret; } 6.延迟更新 void pushDown(int m, int rt) { if(!col[rt]) return ; col[rt << 1] = col[rt << 1 | 1] = col[rt]; col[rt] = 0; mag[rt << 1] = col[rt << 1] * (m - (m >> 1)); mag[rt << 1 | 1] = col[rt << 1 | 1] * (m >> 1); } 7.成段更新 void pushDown(int m, int rt) { if(!col[rt]) return ; col[rt << 1] = col[rt << 1 | 1] = col[rt]; col[rt] = 0; mag[rt << 1] = col[rt << 1] * (m - (m >> 1)); mag[rt << 1 | 1] = col[rt << 1 | 1] * (m >> 1); } 8.放个程序:upc3453 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 const int Maxn = 100000 + 2; long long mag[Maxn << 2]; long long col[Maxn << 2]; inline void pushUp(int rt) { mag[rt] = mag[rt << 1] + mag[rt << 1 | 1]; } void build(int l, int r, int rt) { col[rt] = 0; if(l == r) { mag[rt] = 0; return ; } int m = (l + r) >> 1; build(lson); build(rson); pushUp(rt); } inline void pushDown(int m, int rt) { if(!col[rt]) return ; col[rt << 1] = col[rt << 1 | 1] = col[rt]; col[rt] = 0; mag[rt << 1] = (long long) col[rt << 1] * (m - (m >> 1)); mag[rt << 1 | 1] = (long long) col[rt << 1 | 1] * (m >> 1); } inline void update(int x, int L, int R, int l, int r, int rt) { if(L <= l && R >= r) { col[rt] = x; mag[rt] = (long long)(r - l + 1) * x; return ; } int m = (l + r) >> 1; pushDown(r - l + 1, rt); if(L <= m) update(x, L, R, lson); if(R > m) update(x, L, R, rson); pushUp(rt); } int main() { int N; scanf("%d", &N); for(int t = 1; t <= N; t++) { int n, m; scanf("%d%d", &n, &m); build(1, n, 1); for(int i = 1; i <= m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); update(a, b, c, 1, n, 1); } printf("%lld\n", mag[1]); } return 0; } 9.二维线段树POJ2155 #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 bool seg[4010][4010]; int n,m,T,ans; void buildy(int i,int l,int r,int rt) { seg[i][rt] = 0; if(l == r) return ; int m = (l + r) >> 1; buildy(i,lson); buildy(i,rson); } void buildx(int l,int r,int rt) { buildy(rt,1,n,1); if(l == r) return ; int m = (l + r) >> 1; buildx(lson); buildx(rson); } void updatey(int i,int L,int R,int l,int r,int rt) { if(L <= l && r <= R) { seg[i][rt]^= 1; return ; } int m = (l + r) >> 1; if(m >= L) updatey(i,L,R,lson); if(m < R) updatey(i,L,R,rson); } void updatex(int L,int R,int y1,int y2,int l,int r,int rt) { if(L <= l && r <= R) { updatey(rt,y1,y2,1,n,1); return ; } int m = (l + r) >> 1; if(L <= m) updatex(L,R,y1,y2,lson); if(R > m) updatex(L,R,y1,y2,rson); } void queryy(int i,int y,int l,int r,int rt) { ans^= seg[i][rt]; if(l == r) return ; int m = (l + r) >> 1; if(y <= m) queryy(i,y,lson); else queryy(i,y,rson); } void queryx(int x,int y,int l,int r,int rt) { queryy(rt,y,1,n,1); if(l == r) return ; int m = (l + r) >> 1; if(x <= m) queryx(x,y,lson); else queryx(x,y,rson); } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); buildx(1,n,1); for(int i = 0 ; i < m ; i++) { char s[2]; scanf("%s",s); if(s[0] == ‘C‘) { int x1,x2,y1,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); updatex(x1,x2,y1,y2,1,n,1); } else { ans = 0; int x,y; scanf("%d%d",&x,&y); queryx(x,y,1,n,1); printf("%d\n",ans); } } if(T) printf("\n"); } return 0; } 注意: 比较符号、对象 区间更新,注意染色边界
以上是关于线段树的主要内容,如果未能解决你的问题,请参考以下文章