NEFU 1266 快乐的雨季 (线段树)

题意:

中文

思路:

线段树基础题当然亦可以分块做

代码:

线段树:

#include <bits/stdc++.h>
using namespace std;
#define ls l,mid,rt*2
#define rs mid+1,r,rt*2+1
#define mi (l+r)/2
const int MAXN=1e5+7;
int n,m;
long long sum[MAXN*4];
int lazy[MAXN*4],st,en,v;
void push_down(int l,int r,int rt){
    if(lazy[rt]){
        int mid=mi;
        lazy[rt*2+1]+=lazy[rt];
        lazy[rt*2]+=lazy[rt];
        sum[rt*2+1]+=(long long)lazy[rt]*(r-mid);
        sum[rt*2]+=(long long)lazy[rt]*(mid-l+1);
        lazy[rt]=0;
    }
}

void push_up(int rt){
    sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void build(int l,int r,int rt){
    sum[rt]=lazy[rt]=0;
    if(l==r){
        return ;
    }
    int mid=mi;
    build(ls);
    build(rs);
}

long long update_and_query(int l,int r,int rt){
    if(r<st||l>en) return 0;
    if(st<=l&&r<=en){
        lazy[rt]+=v;
        sum[rt]+=(long long)v*(r-l+1);
        return sum[rt];
    }
    push_down(l,r,rt);
    int mid=mi;
    long long ans=update_and_query(ls)+update_and_query(rs);
    push_up(rt);
    return ans;
}
int main(){
    freopen("data.in","r",stdin);
    freopen("out.txt","w",stdout);
    while(scanf("%d%d",&n,&m)!=-1){
        build(1,n,1);
        while(m--){scanf("%d%d%d",&st,&en,&v);
            printf("%lld\n",update_and_query(1,n,1));
        }
    }
}
分块:

#include <iostream>
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

const int MAXN=1e5+7;
int n,m;
int blen,belong[MAXN],r[MAXN],l[MAXN],num;
long long sum[MAXN],a[MAXN];
int lazy[MAXN];
void build(){
    blen=sqrt(n);
    num=n/blen;
    if(n%blen) n++;
    for(int i=1;i<=num;i++) l[i]=blen*(i-1)+1,r[i]=blen*i;
    r[num]=n;
    for(int i=1;i<=num;i++){
        sum[i]=lazy[i]=0;
        for(int j=l[i];j<=r[i];j++){
            belong[j]=i;
            a[j]=0;
        }
    }
}
long long update_and_query(int st,int en,int v){
    long long ans=0;
    if(belong[st]==belong[en]){
        for(int i=st;i<=en;i++){
            a[i]+=v;
            ans+=a[i]+lazy[belong[st]];
        }
        sum[belong[st]]+=(long long)v*(en-st+1);
    }else{
        for(int i=st;i<=r[belong[st]];i++){
            a[i]+=v;
            ans+=a[i]+lazy[belong[st]];
        }
        sum[belong[st]]+=(long long)v*(r[belong[st]]-st+1);
        for(int i=belong[st]+1;i<belong[en];i++){
            sum[i]+=(long long)v*(r[i]-l[i]+1);
            lazy[i]+=v;
            ans+=sum[i];
        }
        for(int i=l[belong[en]];i<=en;i++){
            a[i]+=v;
            ans+=a[i]+lazy[belong[en]];
        }
        sum[belong[en]]+=(long long)v*(en-l[belong[en]]+1);
    }
    return ans;
}
int main(){
    //freopen("data.in","r",stdin);
    //freopen("out.txt","w",stdout);
    while(scanf("%d%d",&n,&m)!=-1){
        build();
        while(m--){int st,en,v;
            scanf("%d%d%d",&st,&en,&v);
            printf("%lld\n",update_and_query(st,en,v));
        }
    }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值