http://acm.hdu.edu.cn/showproblem.php?pid=1698
题意:给定一根棒的长度,它上面有价值1,2,3种,初始价值为1,每次输入的x,y,z表示把区间[x,y]的价值全部变为z;问最后这根棒的总价值是多少。
思路:与书中对某一线段[x,y]同时加上z类似,只不过这个是把线段[x,y]变成z。很经典的应用。
属于线段树成段更新问题。。成段更新与单点更新不同,成段更新没必要更新到单个点,当找到要更新的区间时直接更新这一整个区间返回即可,若上面没有返回,就要传递属性,即把该区间的价值属性传递给左右儿子,同时更新该节点的信息,并且把该区间的价值属性设为-1,标志它已把价值传递给左右子树了。最后更新完子树后要回溯更新这个节点的信息。
询问区间的和时,若正好询问到该区间并且价值和一定时直接返回价值和,若它的价值属性是-1要递归左右子树求和。否则将信息向下推送,直到找到相等的区间。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL long long #define _LL __int64 #define eps 1e-12 #define PI acos(-1.0) #define C 240 #define S 20 using namespace std; const int maxn = 100010; struct node { int l,r; int val; //维护该区间的价值 int sum;//维护该区间的价值和 }tree[maxn*4]; void build(int v, int l, int r) { tree[v].l = l; tree[v].r = r; tree[v].val = 1; tree[v].sum = 1; if(l == r) { return; } int mid = (l+r) >> 1; build(v*2,l,mid); build(v*2+1,mid+1,r); tree[v].sum = tree[v*2].sum + tree[v*2+1].sum; } void update(int v, int l, int r, int val) { if(tree[v].l == l && tree[v].r == r) { tree[v].val = val; tree[v].sum = val*(tree[v].r - tree[v].l + 1); return; } if(tree[v].val != -1) { int mid = (tree[v].l + tree[v].r) >> 1; tree[v].sum = tree[v].val*(tree[v].r - tree[v].l + 1); //向下推送同时更新该节点的价值和 update(v*2,tree[v].l,mid,tree[v].val); update(v*2+1,mid+1,tree[v].r,tree[v].val); tree[v].val = -1; //价值置为1,因为向下推送了。 } int mid = (tree[v].l + tree[v].r) >> 1; if(r <= mid) update(v*2,l,r,val); else if(l > mid) update(v*2+1,l,r,val); else { update(v*2,l,mid,val); update(v*2+1,mid+1,r,val); } tree[v].sum = tree[v*2].sum + tree[v*2+1].sum; //回溯更新该节点 } int query(int v, int l, int r) { if(tree[v].l == l && tree[v].r == r) { if(tree[v].val != -1) return tree[v].val * (tree[v].r - tree[v].l + 1); else { //若是-1,递归计算左右子树 int mid = (tree[v].l + tree[v].r) >> 1; return query(v*2,l,mid) + query(v*2+1,mid+1,r); } } int mid = (tree[v].l + tree[v].r) >> 1; //上面没走掉,要将信息向下推送,同时将该节点价值置为-1 if(tree[v].val != -1) { update(v*2,tree[v].l,mid,tree[v].val); update(v*2+1,mid+1,tree[v].r,tree[v].val); tree[v].val = -1; } if(r <= mid) return query(v*2,l,r); else if(l > mid) return query(v*2+1,l,r); return query(v*2,l,mid) + query(v*2+1,mid+1,r); } int main() { int test; int n,m; int l,r,val; scanf("%d",&test); for(int item = 1; item <= test; item++) { scanf("%d",&n); build(1,1,n); scanf("%d",&m); while(m--) { scanf("%d %d %d",&l,&r,&val); update(1,l,r,val); } printf("Case %d: The total value of the hook is %d.\n",item,query(1,1,n)); } return 0; }
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL long long #define _LL __int64 #define eps 1e-12 #define PI acos(-1.0) #define C 240 #define S 20 using namespace std; const int maxn = 100010; struct node { int l,r; int val; //维护该区间的价值 }tree[maxn*4]; void build(int v, int l, int r) { tree[v].l = l; tree[v].r = r; tree[v].val = 1; if(l == r) { return; } int mid = (l+r) >> 1; build(v*2,l,mid); build(v*2+1,mid+1,r); } void update(int v, int l, int r, int val) { if(tree[v].l == l && tree[v].r == r) { tree[v].val = val; return; } if(tree[v].val != -1) { tree[v*2].val = tree[v].val; tree[v*2+1].val = tree[v].val; tree[v].val = -1; //价值置为1,因为向下推送了。 } int mid = (tree[v].l + tree[v].r) >> 1; if(r <= mid) update(v*2,l,r,val); else if(l > mid) update(v*2+1,l,r,val); else { update(v*2,l,mid,val); update(v*2+1,mid+1,r,val); } } int query(int v, int l, int r) { if(tree[v].val != -1) { return tree[v].val * (r - l + 1); } int mid = (tree[v].l + tree[v].r) >> 1; if(r <= mid) return query(v*2,l,r); else if(l > mid) return query(v*2+1,l,r); else return query(v*2,l,mid) + query(v*2+1,mid+1,r); } int main() { int test; int n,m; int l,r,val; scanf("%d",&test); for(int item = 1; item <= test; item++) { scanf("%d",&n); build(1,1,n); scanf("%d",&m); while(m--) { scanf("%d %d %d",&l,&r,&val); update(1,l,r,val); } printf("Case %d: The total value of the hook is %d.\n",item,query(1,1,n)); } return 0; }