您的位置:首页 > 编程语言

HDU1698关于线段树的解题报告和代码

2010-08-03 16:33 344 查看
首先用的数据结构是线段树,这个大家可以去搜索下,本身的数据结构是很简单的,但是变化是非常广的,这就是线段树的魅力所在,这题用线段的主要思想就是把域Cover定位是否整个覆盖,比如[1,5]这个区间的覆盖标记是1说明完全覆盖,所以马上可以算出答案(5-1+1)×val,val为覆盖这个线段的钩子等级,这题主要是考更新,更新的时候要通过判断Cover来做即时更新,如果Cover是0的话那可以按照普通方法来更新,但是如果Cover是1的话那就先要把父节点的相关信息传递给左右儿子,然后改变自己相关信息才可,具体比较难阐述,还是要大家仔细想想,下面放上代码,还有一个小插曲,话说它题目的描述是到10w因此一开始我只开了100010的数组结果一直WA,然后试了下20W结果过了,题目描述还有是有点问题
#include<iostream>
using namespace std;
const int Max=200010;
int N,M;
//采用静态的树结构
struct Node
{
int l,r;
Node *lc,*rc;
//覆盖标记,表示这一段是不是完全覆盖
int Cover;
//记录当前节点的值
int Val;
}No[Max];
int TreeLen;
//新建,每次分配空间
Node *new_node()
{
Node * pt = &No[TreeLen++];
memset(pt,0,sizeof(Node));
return pt;
}
//建树
Node* MakeTree(int l,int r)
{
//每次都初始化一个节点
Node *root= new_node();
int Mid;
root->l=l;
root->r=r;
root->Cover=1;
root->Val=1;
if(l!=r)
{
//递归整棵树
Mid=(l+r)/2;
root->lc=MakeTree(l,Mid);
root->rc=MakeTree(Mid+1,r);
}
//返回根节点
return root;
}
void Update(Node* root ,int l,int r,int Val)
{
int Mid=(root->l+root->r)/2;
if(root->l==l&&root->r==r)
{
//如果找到完全覆盖的,覆盖标记记为1,然后把值赋给Val
root->Cover=1;
root->Val=Val;
return ;
}
//如果之前赋值过的话,则要把值全部传递给子树
if(root->Cover)
{
// 把值传递给左儿子
root->lc->Cover=1;
root->lc->Val=root->Val;
// 把值传递给右儿子
root->rc->Cover=1;
root->rc->Val=root->Val;
root->Cover=0;
}
//递归更新直到要更新的全部更新
if(l>Mid)
{
Update(root->rc,l,r,Val);
}
else
if(r<=Mid)
{
Update(root->lc,l,r,Val);
}
else
{
Update(root->lc,l,Mid,Val);
Update(root->rc,Mid+1,r,Val);
}
}
//求答案
int GetVal(Node *root)
{
//如果覆盖标记为1说明该段全部被覆盖求出值
if(root->Cover)
{
return (root->r-root->l+1)*(root->Val);
}
//负责递归直到找到子树是完全覆盖的
else
{
return GetVal(root->lc)+GetVal(root->rc);
}
}
int main()
{
int T,i;
scanf("%d",&T);
int X,Y,Z;
int Time=1;
while(T--)
{
TreeLen=0;
scanf("%d%d",&N,&M);
Node* Root=MakeTree(1,N);
for(i=0;i<M;i++)
{
scanf("%d%d%d",&X,&Y,&Z);
Update(Root,X,Y,Z);
}
printf("Case %d: The total value of the hook is %d./n",Time++,GetVal(Root));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: