分析:线段树的应用,区间修改,使用延迟标记进行延迟修改。
#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;
}
HDU ACM 1698 Just a Hook->线段树+区间修改
原文地址:http://blog.csdn.net/a809146548/article/details/45458511