poj 3468(线段树 lazy思想)

这道题和poj2777是一模一样的 模版都是一样的 使用lazy思想 这个思想我也不太好解释 其实就是
核心:
先懒着
对 没错 就是先懒着 updata的时候 不更新到叶子节点 先保存之后就放着不管
当你需要这个区间的时候再次展开 这样其实有的区间原来展开了 但是你不查询并没有什么用
所以这里的”先懒着”思想 很好的利用了题目的已知条件 只对需要查询的区间展开
美丽的姿势 避免了tle的悲剧

#include<cstdio>
//#include<time.h>
#include<stdlib.h>
const int maxn=1e5+5;
typedef long long ll;
struct note{
    int l,r;
    ll sum,cover;
}a[(maxn<<2)];
void init_(int i,int l,int r){
    a[i].l=l;
    a[i].r=r;
    a[i].sum=0;
    a[i].cover=0;
    if(l==r){
        scanf("%lld",&a[i].sum);return ;
    }
    int mid_=(l+r)>>1;
    init_(i<<1,l,mid_);
    init_(i<<1 |1,mid_+1,r);
    a[i].sum=a[i<<1].sum+a[i<<1 |1].sum;
}
void scanf_(char& t){
    while((t=getchar())&&(t!='Q'&&t!='C')){}
}
ll calc(int x,int y,int judge){
    ll sum_=(ll)(y-x+1);
    ll mid=sum_>>1;
    if(!judge)return sum_-mid;
    return mid;
}
ll getsum(int i,int start,int aim){
    if(a[i].l==start&&a[i].r==aim)
        return a[i].sum;
    if(a[i].cover){

        a[i<<1].cover+=a[i].cover;
        a[i<<1 |1].cover+=a[i].cover;
        a[i<<1].sum+=a[i].cover*calc(a[i].l,a[i].r,0);
        a[i<<1 |1].sum+=a[i].cover*calc(a[i].l,a[i].r,1);
        a[i].cover=0;
    }
    int mid=(a[i].l+a[i].r)>>1;
    if(start>mid)return getsum(i<<1 |1,start,aim);
    else if(aim<=mid)return getsum(i<<1,start,aim);
    else return getsum(i<<1,start,mid)+getsum(i<<1 |1,mid+1,aim);
}
void updata(int i,int start,int aim,int data){
    if(a[i].l==start&&a[i].r==aim){
        a[i].cover+=data;
        a[i].sum+=(data*(aim-start+1));
        return;
    }
    if(a[i].cover){
        a[i<<1].cover+=a[i].cover;
        a[i<<1 |1].cover+=a[i].cover;
        a[i<<1].sum+=(a[i].cover*calc(a[i].l,a[i].r,0));
        a[i<<1 |1].sum+=(a[i].cover*calc(a[i].l,a[i].r,1));
        a[i].cover=0;
    }
    int mid=(a[i].l+a[i].r)>>1;
    if(start>mid){
        updata(i<<1 |1,start,aim,data);
    }
    else if(aim<=mid) updata(i<<1,start,aim,data);
    else{
        updata(i<<1,start,mid,data);
        updata(i<<1 |1,mid+1,aim,data);
    }
    a[i].sum=a[i<<1].sum+a[i<<1 |1].sum;
}

int main(){
    int n,m;
// freopen("in6.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=-1){
        init_(1,1,n);
        while(m--){
            char t;
            int x,y,z;
            scanf_(t);
            if(t=='Q'){
                scanf("%d%d",&x,&y);
                printf("%lld\n",getsum(1,x,y));
            }
            else{
                scanf("%d%d%d",&x,&y,&z);
                updata(1,x,y,z);
            }
        }
    }
    return 0;
}
//const int coun=0x3fffffff;
// clock_t t1,t2,t3;
// m=10;
// while(m--){
// t1=clock();
// for(int i=0;i<coun;i++){
// int x=i,y=i+1;
// if(x&1){
// x=y;
// }
// if(!(x^y)){
//
// }
// }
// t2=clock();
// for(int i=0;i<coun;i++){
// int x=i,y=i+1;
// if(x%2==1){
// x=y;
// }
// if(x==y){
//
// }
// }
// t3=clock();
// printf("%.3lf %.3lf\n",(t2-t1)/1000.0,(t3-t2)/1000.0);
// }

你可能感兴趣的:(poj 3468(线段树 lazy思想))