HDU 1698 Just a Hook(线段树区间更新)

来源:互联网 发布:ssh怎么指定端口号 编辑:程序博客网 时间:2024/04/29 22:09

题意:

屠夫是Dota中一个令所有英雄闻风丧胆的英雄。他有一个很长的钩子,这个钩子是用铜做的(刚刚开始都是1),现在他想要更改这些钩子,把某个区间的钩子改为金、银或铜。
输入 L, R, X 表示把 L~R的区间的数字改为 X。最后求[1, N]的和。

解析:

这题是线段树区间修改的模板题。
更新的时候采用了一种叫做延迟更新的技术,即需要更新某个区间的时候,暂时只更新这个区间,其子区间在有需要的时候再更新(否则每次更新都要遍历到子区间,时间复杂度会大大的上升),于是又加了一个setv的延迟标志(有值表示没有向下更新的,没有值表示已经“最新”)

AC代码

#include <cstdio>#include <cstring>#include <algorithm>#define ls o*2#define rs o*2+1using namespace std;typedef long long ll;const int INF = 0x3f3f3f3f;const int N = 1e5 + 10;int ql, qr, val;int sumv[N<<2], setv[N<<2];void maintain(int o) {    sumv[o] = sumv[ls] + sumv[rs];}void build(int o, int L, int R) {    setv[o] = 0;    sumv[o] = 1;    if(L == R)        return;    int M = (L+R)/2;    build(ls, L, M);    build(rs, M+1, R);}void pushdown(int o, int M) {    if(setv[o]) {        setv[ls] = setv[rs] = setv[o];        sumv[ls] = (M-(M>>1)) * setv[o];         sumv[rs] = (M>>1) * setv[o];        setv[o] = 0;    }}void modify(int o, int L, int R) {    if(ql <= L && R <= qr) {        setv[o] = val;        sumv[o] = val * (R-L+1);        return;    }    pushdown(o, R-L+1);    int M = (L+R)/2;    if(ql <= M) modify(ls, L, M);    if(qr > M) modify(rs, M+1, R);    maintain(o);}int _sum;void query(int o, int L, int R) {    if(setv[o]) {        _sum += setv[o] * (min(R, qr) - max(L,ql) + 1);    }else if(ql <= L && R <= qr) {        _sum += sumv[o];    }else {        int M = (L+R)/2;        if(ql <= M) query(ls, L, M);        if(qr > M) query(rs, M+1, R);    }}int main() {    int n, q;    int T, cas = 1;    scanf("%d", &T);    while(T--) {        scanf("%d%d", &n, &q);        build(1, 1, n);        while(q--) {            scanf("%d%d%d", &ql, &qr, &val);            modify(1, 1, n);        }        ql = 1, qr = n, _sum = 0;        query(1, 1, n);        printf("Case %d: The total value of the hook is %d.\n", cas++, _sum);    }    return 0;}
0 0
原创粉丝点击