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

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

#define ll long long
using namespace std;
ll n,m,a[2000000];
struct node{
    ll sum,add;//区间总和 懒标记
    ll l,r;
}t[2000000];
ll read(){
    long long x=0,f=1;
    char c=getchar();
    while((c<'0'||c>'9')&&c!='-')c=getchar();
    if(c=='-')f=-1,c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return f*x;
}
void build(ll p,ll l,ll r){
    t[p].l=l,t[p].r=r,t[p].sum=0;
    if(l==r){t[p].sum=1;return ;}
    ll mid=(l+r)>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;
}

void spread(ll p){//下传懒惰标记
    if(t[p].add) {
//        ll m=t[p].r-t[p].l+1;
//        t[p*2].sum=(m-(m>>1))*t[p].add;//如上所说修改
//        t[p*2+1].sum=(m>>1)*t[p].add;
        t[p*2].sum=(t[p*2].r-t[p*2].l+1)*t[p].add;//如上所说修改
        t[p*2].add=t[p].add;
        t[p*2+1].sum=(t[p*2+1].r-t[p*2+1].l+1)*t[p].add;
        t[p*2+1].add=t[p].add;
        t[p].add=0;//别忘记清空!!
    }

}
void add(ll p,ll l,ll r,ll k){
    if(t[p].l>=l&&t[p].r<=r){

        t[p].sum=(ll)(t[p].r-t[p].l+1)*k;//不要忘了 区间长度减掉原区间和
        t[p].add=k;
        return ;
    }
    spread(p);
    ll mid=(t[p].l+t[p].r)>>1;//记得是在这个节点记录的区间的中点
    if(l<=mid)add(p*2,l,r,k);//注意是l<=mid否则当修改区间横跨了mid时就不会进行任何操作
    if(r>mid)add(p*2+1,l,r,k);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;//还要记得修改sum
}
ll ask(ll p,ll l,ll r){//查询
    if(t[p].l>=l&&t[p].r<=r){
        return t[p].sum;
    }
    spread(p);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;//每次spread之后都要从新统计sum!
    ll mid=(t[p].r+t[p].l)>>1;
    ll val=0;
    if(l<=mid)val+=ask(p*2,l,r);
    //如果这里修改为l~mid下面改成mid+1~r,则下一次进入ask函数的mid
    //就会比这一次的r大了,因为mid是该节点的中间点,mid=(t[p].r+t[p].l)>>1
    //后来我想改成mid=(l+r)>>1配套l~mid和mid+1~r,但这样会出现更严重的问题,
    //假设询问的区间全部位于整棵树的左子树,这个时候会出现
    //到整棵树的右子树中去求询问区间的右半边的情况,找了个寂寞!(感谢mrgg的提醒)
    if(r>mid)val+=ask(p*2+1,l,r);
    return val;
}
int main(){
    int T;
    cin>>T;
    memset(a,0, sizeof(a));
    for(int j=1;j<=T;j++){

        cin>>n>>m;
        for(ll i=1;i<=n;i++){
            a[i]=1;
            t[i].add=0;
        }

        build(1,1,n);
        for(ll i=1;i<=m;i++){
            ll x=read(),y=read(),cm=read();
            add(1,x,y,cm);
//            printf("Case %d:  %d.\n",j, t[1].sum);
        }
        printf("Case %d: The total value of the hook is %d.\n",j, t[1].sum);
//        printf("Case %d: The total value of the hook is %d.",j, ask(1,1,n));
    }

}

调了20多次,加了这两个终于过了

    memset(a,0, sizeof(a));

            t[i].add=0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值