HDU 1698 Just a Hook(线段树的区间修改)

思路:

这题考察线段树的区间修改,如果不做优化会使复杂度非常糟糕,优化的办法就是用lazy-tag方法。当修改的区间覆盖当前遍历到的区间时,只对当前结点做出修改,不继续深入,并给它做标记,在代码中体现在rcd[]数组中。当需要继续深入时,采用push_down方法去更新它的子节点;

代码:

#include<iostream>
using namespace std;
template <class T>
inline bool read(T &ret){
    char c; int sgn;
    if(c=getchar(),c==EOF) return 0; //EOF
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn; return 1;
}
const int MAX_N=1e5+99;
int sum[MAX_N<<2],rcd[MAX_N<<2];
void push_up(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void push_down(int rt,int m){
    if(rcd[rt]){
        rcd[rt<<1]=rcd[rt<<1|1]=rcd[rt];
        sum[rt<<1]=(m-(m>>1))*rcd[rt];
        sum[rt<<1|1]=(m>>1)*rcd[rt];
        rcd[rt]=0;
    }
}
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
void build(int l,int r,int rt){
    rcd[rt]=0;
    if(l==r) {sum[rt]=1;return;}
    int mid=(l+r)>>1;
    build(lson),build(rson);
    push_up(rt);
}
void update(int a,int b,int c,int l,int r,int rt){
    if(a<=l&&b>=r){
        sum[rt]=(r-l+1)*c;
        rcd[rt]=c;
        return;
    }
    push_down(rt,r-l+1);
    int mid=(l+r)>>1;
    if(a<=mid) update(a,b,c,lson);
    if(b>mid) update(a,b,c,rson);
    push_up(rt);
}
int main(){
    int kase; read(kase);
    for(int i=1;i<=kase;i++){
        int n,q; read(n); read(q);
        build(1,n,1);
        while(q--){
            int x,y,z;
            read(x); read(y); read(z);
            update(x,y,z,1,n,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",i,sum[1]);
    }
    return 0; 
}
posted @ 2019-11-27 16:07  YuhanのBlog  阅读(99)  评论(0编辑  收藏  举报