您的位置:首页 > 其它

hdu1698 Just a Hook (线段树)

2017-11-14 20:35 204 查看
题意:给一个大小为n的数组,初始状态全为1 ,进行q次段赋值,问最后的全段和是多少

思路:线段树段修改模板题(用来写模板的题)特别的是,由于只有最后一步查询全段和以及初始状态全为1,代码可以偷工减料

#include <cstdio>
#include<iostream>
using namespace std;
const int maxn=500100;

//用于存放线段树的结构 l,r表示此区间的左右端点
struct segn
{
int su,mark_add;
}segt[maxn];
//建树:叶节点终止条件->递归建左右子树->由左右孩子信息得到此节点信息
void push_dowm(int root,int st,int en)
{
if(segt[root].mark_add!=0)
{
segt[root*2+1].su=((st+en)/2-st+1)*segt[root].mark_add;
segt[root*2+2].su=(en-(st+en)/2)*segt[root].mark_add;
segt[root*2+1].mark_add=segt[root].mark_add;
segt[root*2+2].mark_add=segt[root].mark_add;
segt[root].mark_add=0;
}
}
void build(int root,int st,int en)
{
//st,en表示目前区间的首尾端点序号,dat[]表示用于初始化的数据
//记录左右端点

if(st==en)//在叶子节点上加入元素数据
{
segt[root].mark_add=0;
segt[root].su=1;//求区间和的操作
return;
}
//对于非叶子节点
int mid=(st+en)/2;//分割点
//由二叉性,数组存树的左右节点编号分别为此节点的*2+1和*2+2
build(root*2+1,st,mid);//递归建左子树
build(root*2+2,mid+1,en);//右子树
//由左右子树得到此节点的数据
//求区间最小值

//求区间和
segt[root].su=segt[root*2+1].su+segt[root*2+2].su;
}

void segadd(int qst,int qen,int tst,int ten,int root,int addnum)
{//全段加

if(qst>ten||qen<tst)//不符合的区间
{
return ;
}
if(tst>=qst&&ten<=qen)//找到要加的区间
{
segt[root].mark_add=addnum;
segt[root].su=addnum*(ten-tst+1);

return ;
}
int mid =(tst+ten)/2;
push_dowm(root,tst,ten);
segadd(qst,qen,tst,mid,root*2+1,addnum);
segadd(qst,qen,mid+1,ten,root*2+2,addnum);//搜索左右子树
}
void upd(int root,int st,int en)
{
if(st==en)return;
push_dowm(root,st,en);
upd(2*root+1,st,(st+en)/2);
upd(
9a70
2*root+2,(st+en)/2+1,en);
segt[root].su=segt[root*2+1].su+segt[root*2+2].su;
}
int main()
{
int c;
scanf("%d",&c);
for(int cas=1;cas<=c;cas++)
{
int n,q,st,en,va;
scanf("%d%d",&n,&q);
build(0,0,n-1);
while(q--)
{
scanf("%d%d%d",&st,&en,&va);
segadd(st-1,en-1,0,n-1,0,va);

}upd(0,0,n-1);

printf("Case %d: The total value of the hook is %d.\n",cas,segt[0].su);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: