题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698
题目大意:有一个长度为n(100000)的钩子,没个单位长度的钩子有金,银,铜三者之一构成,价值分别为3,2,1,现在进行Q(100000)次操作,每次操作表示把一个区间[l,r]内的钩子变成一种颜色,问Q次操作之后钩子的总价值。
分析:我们用线段树来纪录每一个区间内的颜色,更新到区间为止。
实现代码如下:
#include <cstdio> using namespace std; const int maxn=1000005; struct segment { int l,r; int mid() { return (l+r)>>1; } int ins; //纪录区间的改变值 }tree[maxn<<2]; void build(int root,int l,int r) { tree[root].l=l; tree[root].r=r; tree[root].ins=1; if(l==r) return ; int mid=tree[root].mid(); build(root<<1,l,mid); build(root<<1|1,mid+1,r); } void update(int root,int l,int r,int v) { if(tree[root].ins==v) return ; if(tree[root].l==l&&tree[root].r==r) { tree[root].ins=v; return ; } if(tree[root].ins!=-1) {//该区间只有一种颜色,更新子树的权值等于父节点的权值 tree[root<<1].ins=tree[root].ins; tree[root<<1|1].ins=tree[root].ins; tree[root].ins=-1;//标记该区间为杂色 } //父节点为杂色时对所有子节点进行更新 int mid=tree[root].mid(); if(r<=mid) update(root<<1,l,r,v); else if(l>mid) update(root<<1|1,l,r,v); else { update(root<<1,l,mid,v); update(root<<1|1,mid+1,r,v); } } int query(int root) { if(tree[root].ins!=-1) return (tree[root].r-tree[root].l+1)*tree[root].ins; else return query(root<<1)+query(root<<1|1); } int main() { int n,q,t,T=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&q); build(1,1,n); while(q--) { int l,r,v; scanf("%d%d%d",&l,&r,&v); update(1,l,r,v); } printf("Case %d: The total value of the hook is %d.\n",T++,query(1)); } return 0; }