分析:线段树的应用,区间修改,使用延迟标记进行延迟修改。
#include<iostream> using namespace std; #define N 100010 class SegmentTree { private: struct Node { int left,right; //左右子节点 int sum; //区间和 int lazy; //延迟标记 }; public: void BuildTree(int root,int l,int r); void Change(int root,int l,int r,int c); int Query(int root); private: Node m_Tree[N<<2]; }; int SegmentTree::Query(int root) { return m_Tree[root].sum; } void SegmentTree::Change(int root,int l,int r,int c) { int mid,x,y; x=m_Tree[root].left; y=m_Tree[root].right; if(l==x && r==y) { m_Tree[root].lazy=1; m_Tree[root].sum=(y-x+1)*c; //区间的每个点都被修改为c,和就等于点数乘以c return ; } mid=(x+y)>>1; if(m_Tree[root].lazy==1) //该if处理延迟更新 { m_Tree[root].lazy=0; Change(2*root+1,x,mid,m_Tree[root].sum/(y-x+1)); //m_Tree[root].sum/(r-l+1)即可得到之前保留的单个点的值 Change(2*root+2,mid+1,y,m_Tree[root].sum/(y-x+1)); } if(l<=mid) Change(2*root+1,l,mid<r?mid:r,c); //该两句更新包含三种情况,更新区间在mid左边,在右边,左右两边均有 if(r>mid) Change(2*root+2,mid+1>l?mid+1:l,r,c); m_Tree[root].sum=m_Tree[root*2+1].sum+m_Tree[root*2+2].sum; } void SegmentTree::BuildTree(int root,int l,int r) { int mid; m_Tree[root].left=l; m_Tree[root].right=r; m_Tree[root].sum=r-l+1; //刚开始区间和等于区间的点数 m_Tree[root].lazy=1; //设置延迟标记 if(l==r) return ; mid=(l+r)>>1; BuildTree(2*root+1,l,mid); //构建左子树 BuildTree(2*root+2,mid+1,r); //构建右子树 } SegmentTree seg_tree; int main() { int T,n,Q,X,Y,Z,i; scanf("%d",&T); i=0; while(T--) { scanf("%d",&n); seg_tree.BuildTree(0,0,n-1); scanf("%d",&Q); while(Q--) { scanf("%d %d %d",&X,&Y,&Z); seg_tree.Change(0,X-1,Y-1,Z); } printf("Case %d: The total value of the hook is %d.\n",++i,seg_tree.Query(0)); } return 0; }
时间: 2024-10-25 07:25:37