dreamxr
精诚所至,金石为开!

导航

 

【题目描述】

给定含有n个数的序列,初始状态每个数为1,然后有q个操作,每次改变某段区间的值,求最后的总和。

【思路】

线段树的成段更新,需要用到懒惰标记(lazy_tag)

考虑最朴素的办法,更新区间段的时候从上到下全部更新,但是这样做的话每次更新时间是O(n)的,肯定要TLE。

lazy_tag的思想就是,当更新到某个节点,并且需要更新的区间包含这个节点所代表的区间时,直接更改这个区间,并做懒惰标记,不再继续向下更新,当更新或者询问到这个节点的子节点时,将标记下传。这样做可以大大降低时间复杂度。

#include<cstdio>
#define N 100010
#define lson l,mid,n<<1
#define rson mid+1,r,n<<1|1
using namespace std;
int sum[N<<2],add[N<<2];
int build(int l,int r,int n){
    add[n]=0;
    if(l==r)
    return sum[n]=1;
    int mid=(l+r)>>1;
    return sum[n]=build(lson)+build(rson);
}
void update(int ll,int rr,int aa,int l,int r,int n){
    if(ll==l&&rr==r){
        add[n]=aa;
        sum[n]=aa*(r-l+1);
        return;
    }
    int m=r-l+1;
    if(add[n]!=0){
        add[n<<1]=add[n<<1|1]=add[n];
        sum[n<<1]=add[n]*(m-(m>>1));
        sum[n<<1|1]=add[n]*(m>>1);
        add[n]=0;
    }
    int mid=(l+r)>>1;
    if(rr<=mid)
    update(ll,rr,aa,lson);
    else if(ll>mid)
    update(ll,rr,aa,rson);
    else
    update(ll,mid,aa,lson),update(mid+1,rr,aa,rson);
    sum[n]=sum[n<<1]+sum[n<<1|1];
}
int main(){
    int t,n,q,x,y,z;
    scanf("%d",&t);
    int d=1;
    while(t--){
        scanf("%d",&n);
        build(1,n,1);
        scanf("%d",&q);
        while(q--){
            scanf("%d%d%d",&x,&y,&z);
            update(x,y,z,1,n,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",d++,sum[1]);
    }
    return 0;
}
posted on 2012-07-05 21:44  dreamxr  阅读(151)  评论(0)    收藏  举报