成段更新:
#include <cstdio> #include <algorithm> using namespace std; #define LL long long #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 111111; LL addv[maxn<<2]; LL sumv[maxn<<2]; //int maxv[maxn<<2]; void PushUp(int rt) { // maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]); sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1]; } void PushDown(int rt,int m) { if (addv[rt]) { addv[rt<<1] += addv[rt]; addv[rt<<1|1] += addv[rt]; sumv[rt<<1] += addv[rt] * (m - (m >> 1)); sumv[rt<<1|1] += addv[rt] * (m >> 1); // maxv[rt<<1] += addv[rt]; // maxv[rt<<1|1] += addv[rt]; addv[rt] = 0; } } void build(int l,int r,int rt) { addv[rt] = 0; if (l == r) { scanf("%I64d",&sumv[rt]); //scanf("%d", &maxv[rt]); return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int c,int l,int r,int rt) { if (L <= l && r <= R) { addv[rt] += c; sumv[rt] += (LL)c * (r - l + 1); //maxv[rt] = max(c, maxv[rt]); return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , c , lson); if (m < R) update(L , R , c , rson); PushUp(rt); } LL query(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { //return maxv[rt]; return sumv[rt]; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; LL ret = 0; if (L <= m) ret += query(L, R, lson); //ret = max(ret, query(L , R , lson)); if (m < R) ret += query(L, R, rson); //ret = max(ret, query(L , R , rson)); return ret; } int main() { int N , Q; scanf("%d%d",&N,&Q); build(1 , N , 1); while (Q --) { char op[2]; int a , b , c; scanf("%s",op); if (op[0] == ‘Q‘) { scanf("%d%d",&a,&b); printf("%I64d\n",query(a , b , 1 , N , 1)); } else { scanf("%d%d%d",&a,&b,&c); update(a , b , c , 1 , N , 1); } } return 0; }
成段置值:
#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 111111; int h , w , n; int col[maxn<<2]; int sum[maxn<<2]; void PushUp(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushDown(int rt,int m) { if (col[rt]) { col[rt<<1] = col[rt<<1|1] = col[rt]; sum[rt<<1] = (m - (m >> 1)) * col[rt]; sum[rt<<1|1] = (m >> 1) * col[rt]; col[rt] = 0; } } void build(int l,int r,int rt) { col[rt] = 0; sum[rt] = 1; if (l == r) return ; int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } int query(int L,int R,int l,int r,int rt) {//求和写法,参数信息=>(问询区间左端点,问询区间右端点,总区间左端点,总区间右端点,根节点编号) if (L <= l && r <= R) { return sumv[rt]; } int m = l + ((r - l)>>1); int ret = 0; if (L <= m) ret += query(L , R , lson); if (R > m) ret += query(L , R , rson); return ret; } void update(int L,int R,int c,int l,int r,int rt) { if (L <= l && r <= R) { col[rt] = c; sum[rt] = c * (r - l + 1); return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , c , lson); if (R > m) update(L , R , c , rson); PushUp(rt); } int main() { int T , n , m; scanf("%d",&T); for (int cas = 1 ; cas <= T ; cas ++) { scanf("%d%d",&n,&m); build(1 , n , 1); while (m --) { int a , b , c; scanf("%d%d%d",&a,&b,&c); update(a , b , c , 1 , n , 1); } printf("Case %d: The total value of the hook is %d.\n",cas , sum[1]); } return 0; }
单点更新:
/* 说明: 此模板支持对于线段的单点加减操作更新、区间最值or和的查询 下面主要以求和操作为例,注释部分为求最值功能,根据自己的 需求适当修改模板 验证题目:HDU 1166 敌兵布阵 (以下代码也是解决此题的代码) */ #include <cstdio> #include <algorithm> #include <string.h> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 50005;//maxn = 线段的最大长度 则=> maxn<<2 = 线段树可能的最多结点 //int maxv[maxn<<2];//保存最大值 //int minv[maxn<<2];//保存最小值 int sumv[maxn<<2];//保存区间和 void PushUP(int rt) { //maxv[rt] = max(maxv[rt<<1] , maxv[rt<<1|1]); //minv[rt] = min(minv[rt<<1], minv[rt<<1|1]); sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1]; } void build(int l,int r,int rt) {//设置初始值 if (l == r) { // scanf("%d",&maxv[rt]); // scanf("%d", &minv[rt]); scanf("%d", &sumv[rt]); return ; } int m = l + ((r - l)>>1); build(lson); build(rson); PushUP(rt); } void update(int p,int sc,int l,int r,int rt) {//单点更新,参数(更新点,更新值,总区间左端点,总区间右端点,根节点编号) if (l == r) { //maxv[rt] = sc; //minv[rt] = sc; sumv[rt] += sc; return ; } int m = l + ((r - l)>>1); if (p <= m) update(p , sc , lson); else update(p , sc , rson); PushUP(rt); } // int query(int L,int R,int l,int r,int rt) {//查询最大值的写法、最小值同理、求和区间写法在下面 // if (L <= l && r <= R) { // return maxv[rt]; // } // int m = (l + r) >> 1; // int ret = 0; // if (L <= m) ret = max(ret , query(L , R , lson)); // if (R > m) ret = max(ret , query(L , R , rson)); // return ret; // } int query(int L,int R,int l,int r,int rt) {//求和写法,参数信息=>(问询区间左端点,问询区间右端点,总区间左端点,总区间右端点,根节点编号) if (L <= l && r <= R) { return sumv[rt]; } int m = l + ((r - l)>>1); int ret = 0; if (L <= m) ret += query(L , R , lson); if (R > m) ret += query(L , R , rson); return ret; } int main(void) { int nCase; scanf("%d", &nCase); for(int t = 1; t <= nCase; t++){ memset(sumv, 0, sizeof(sumv)); int len; scanf("%d", &len); build(1, len, 1); char s[20]; printf("Case %d:\n", t); while(~scanf("%s", s) && s[0] != ‘E‘){//s != ‘End‘ if(s[0] == ‘Q‘){//s = Query int L, R; scanf("%d %d", &L, &R); printf("%d\n", query(L, R, 1, len, 1)); } else if(s[0] == ‘S‘){//减操作 int point, val; scanf("%d%d", &point, &val); update(point, -val, 1, len, 1); } else if(s[0] == ‘A‘){//加操作 int point, val; scanf("%d%d", &point, &val); update(point, val, 1, len, 1); } } } return 0; }
融合置值和成段加减 ( 刘汝佳程序 ) :
///op==1是加减更新操作 ///op==其他是置值操作 ///y1是查询时候的左端点 ///y2是查询时候的右端点 const int maxnode = 1<<17; int _sum, _min, _max, op, y1, y2; struct IntervalTree { int sumv[maxnode], minv[maxnode], maxv[maxnode], setv[maxnode], addv[maxnode]; void maintain(int o, int L, int R) { int lc = o*2, rc = o*2+1; if(R > L) { sumv[o] = sumv[lc] + sumv[rc]; minv[o] = min(minv[lc], minv[rc]); maxv[o] = max(maxv[lc], maxv[rc]); } if(setv[o] >= 0) { minv[o] = maxv[o] = setv[o]; sumv[o] = setv[o] * (R-L+1); } if(addv[o]) { minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (R-L+1); } } void pushdown(int o) { int lc = o*2, rc = o*2+1; if(setv[o] >= 0) { setv[lc] = setv[rc] = setv[o]; addv[lc] = addv[rc] = 0; setv[o] = -1; } if(addv[o]) { addv[lc] += addv[o]; addv[rc] += addv[o]; addv[o] = 0; } } void update(int o, int L, int R) { int lc = o*2, rc = o*2+1; if(y1 <= L && y2 >= R) { if(op == 1) addv[o] += v; else { setv[o] = v; addv[o] = 0; } } else { pushdown(o); int M = L + (R-L)/2; if(y1 <= M) update(lc, L, M); else maintain(lc, L, M); if(y2 > M) update(rc, M+1, R); else maintain(rc, M+1, R); } maintain(o, L, R); } void query(int o, int L, int R, int add) { if(setv[o] >= 0) { int v = setv[o] + add + addv[o]; _sum += v * (min(R,y2)-max(L,y1)+1); _min = min(_min, v); _max = max(_max, v); } else if(y1 <= L && y2 >= R) { _sum += sumv[o] + add * (R-L+1); _min = min(_min, minv[o] + add); _max = max(_max, maxv[o] + add); } else { int M = L + (R-L)/2; if(y1 <= M) query(o*2, L, M, add + addv[o]); if(y2 > M) query(o*2+1, M+1, R, add + addv[o]); } } };