您的位置:首页 > 其它

hdu 1698 Just a Hook[线段树,updata成段更新]

2012-11-12 15:38 375 查看
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1698

题目大意:给一个区间1-n,初始化每个值都是1,然后有m个操作,每个操作更新一个区间,输入3个数a, b, c.代表区间a,b的值更新为c。最后求总的值是多少。

思路:线段树成段更新,每一次更新都不需要更新到底部(单点更新),而是更新到tree左端点等于a,右端点等于b即可。

代码:

#include<stdio.h>
#include<string.h>

#define MAXN 100002

int tree[MAXN << 2]; //线段树。
int color[MAXN << 2]; //记录颜色的树,也是一个标记,每次操作都不更新节点,因为直接记录值就能求出最大的。但是本次的结果会影响下一次。这个数组的作用就是对上一次的操作进行更新,但不用更新全部。
int n, m; //n个节点,m次操作。

//向上更新节点。
void PushUp(int rt)
{
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}

//向下更新节点。
void PushDown(int rt, int tot)
{
if( color[rt] ) {
color[rt << 1] = color[rt];
color[rt << 1 | 1] = color[rt];
tree[rt << 1] = (tot - (tot >> 1)) * color[rt];
tree[rt << 1 | 1] = (tot >> 1) * color[rt];
color[rt] = 0;
}
}

void build(int l, int r, int rt)
{
//在建树的时候,颜色全部为0,因为第一次不用更新,更新操作从第二次开始。
color[rt] = 0;
tree[rt] = 1;
if(l == r) return ;
int mid = (l + r) >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
PushUp( rt );
}

void updata(int L, int R, int value, int l, int r, int rt)
{
if(L <= l && R >= r) {
color[rt] = value; //记录当前节点的颜色,但是后面加的是return,并不能执行到PushDown函数。这是因为本次操作不用更行,记录的原因是为了更新下一次。
tree[rt] = value * (r - l + 1); //本次不用更新的原因就是在这里了,直接赋值就OK了啊。
return ;
}
PushDown(rt, r - l + 1);
int mid = (l + r) >> 1;
if(L <= mid) updata(L, R, value, l, mid, rt << 1);
if(R > mid) updata(L, R, value, mid + 1, r, rt << 1 | 1);
PushUp( rt );
}

int main()
{
int T, Case = 0;
scanf("%d", &T);
while( T-- ) {
scanf("%d %d", &n, &m);
build(1, n, 1);
for(int i = 0; i < m; i++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
updata(a, b, c, 1, n, 1);
}
printf("Case %d: The total value of the hook is %d.\n", ++Case, tree[1]);
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: