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

Hdu 1698 【线段树 成段更新】.cpp

2012-10-12 11:21 316 查看
[b]题意:[/b]

  动态更新一段区间的值..

  最后输出总区间的和..



[b]思路:[/b]

  其实就是线段树的成段更新..

  用到了lazy[] 表示懒惰标志..

  懒惰标记:

    就是每次更新不更新到最后..而是更新到包含了区间的最大的节点..

    然后如果下次更新的时候更新到了上次已经更新到的节点..

    那先把上次更新暂停的节点往下更新..直到这次更新的区间最大的节点没有被标记..

 

   这样就省时间了..



[b]Tips:[/b]

    pushdown节点就是用来向下更新的..

    

    要注意的是modify函数..即每次更新的时候 把根节点标记为要更新的数 x

    然后顺便求出最大值sum[rt]..

    同时原节点要还原为非标记状态-1

    

    然后向下pushdown 范围是 R-L+1

[b]Code:[/b]

[b]  [/b]

View Code

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

const int MAXN = 100010;
int sum[MAXN<<2];
int lazy[MAXN<<2];

void pushup(int rt)
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void pushdown(int rt, int x)
{
if(lazy[rt] != -1) {
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
sum[rt<<1] = (x-(x>>1))*lazy[rt];///!!!
sum[rt<<1|1] = (x>>1)*lazy[rt];///!!!
lazy[rt] = -1;
}
}

void creat(int l, int r, int rt)
{
lazy[rt] = -1, sum[rt] = 1;
if(l == r) return;
int mid = (l+r)>>1;
creat(l, mid, rt<<1);
creat(mid+1, r, rt<<1|1);
pushup(rt);
}

void modify(int l, int r, int x, int L, int R, int rt)
{
if(l <= L && r >= R) {
lazy[rt] = x;
sum[rt] = x*(R-L+1);///!!!
return;
}
pushdown(rt, R-L+1);///!!!
int mid = (L+R)>>1;
if(l <= mid) modify(l, r, x, L, mid, rt<<1);
if(r > mid) modify(l, r, x, mid+1, R, rt<<1|1);
pushup(rt);
}

int main()
{
int i, j, k = 0;
int n, T, q;
int x, y, w;
while(scanf("%d", &T) != EOF)
while(T--)
{
scanf("%d %d", &n, &q);
creat(1, n, 1);

while(q--) {
scanf("%d %d %d", &x, &y, &w);
modify(x, y, w, 1, n, 1);
}

printf("Case %d: The total value of the hook is %d.\n", ++k, sum[1]);
}
return 0;
}


[b]题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: